home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsinstall / fsmake.c.debug < prev    next >
Encoding:
Text File  |  1990-02-18  |  76.7 KB  |  2,873 lines

  1. /* 
  2.  * fsmake.c --
  3.  *
  4.  *    Make a sprite file system on a raw disk.
  5.  *
  6.  * IMPORTANT NOTE ABOUT PORTABILITY:
  7.  *
  8.  *    I use the sprite directory format even when I am reading a UNIX
  9.  *    directory.  I can get a way with this because they are the same.  The
  10.  *    reason why I don't use the UNIX one is that on a PMAX there are some
  11.  *    defines in "/usr/include/sys/dir.h" which screw up the compilation
  12.  *    of this file.  If this runs on a UNIX system that does not have
  13.  *    a compatible directory format then the code in CopyTree must be
  14.  *    modified.
  15.  *
  16.  * Copyright (C) 1989 by Digital Equipment Corporation, Maynard MA
  17.  *
  18.  *            All Rights Reserved
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its 
  21.  * documentation for any purpose and without fee is hereby granted, 
  22.  * provided that the above copyright notice appear in all copies and that
  23.  * both that copyright notice and this permission notice appear in 
  24.  * supporting documentation, and that the name of Digital not be
  25.  * used in advertising or publicity pertaining to distribution of the
  26.  * software without specific, written prior permission.  
  27.  *
  28.  * Digitial disclaims all warranties with regard to this software, including
  29.  * all implied warranties of merchantability and fitness.  In no event shall
  30.  * Digital be liable for any special, indirect or consequential damages or
  31.  * any damages whatsoever resulting from loss of use, data or profits,
  32.  * whether in an action of contract, negligence or other tortious action,
  33.  * arising out of or in connection with the use or performance of this
  34.  * software.
  35.  */
  36.  
  37. #ifndef lint
  38. static char rcsid[] = "$Header: /sprite/src/admin/fsinstall/RCS/fsmake.c,v 1.14 90/02/17 23:47:50 nelson Exp Locker: rab $ SPRITE (Berkeley)";
  39. #endif
  40.  
  41. #include "sprite.h"
  42. #include "option.h"
  43. #include "diskUtils.h"
  44. #include <stdio.h>
  45. #include <sys/file.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <sys/dir.h>
  51. #include <assert.h>
  52. #include <sys/time.h>
  53.  
  54. #include <sys/param.h>
  55. #include <sysStats.h>
  56.  
  57.  
  58. #ifdef direct
  59. #undef direct
  60. #endif
  61.  
  62. #if defined(sprite) || defined(sun)
  63. #define S_GFDIR     S_IFDIR
  64. #define S_GFMT      S_IFMT
  65. #define S_GFLNK     S_IFLNK
  66. #define S_GFREG      S_IFREG
  67. #endif
  68.  
  69. extern int errno;
  70. char *__getwd();
  71. char *__malloc();
  72. #include "/sprite/src/lib/c/stdlib/memInt.h"
  73.  
  74. /*
  75.  * Constants settable via the command line.
  76.  */
  77. int kbytesToFileDesc = 4;    /* The ratio of kbytes to
  78.                  * the number of file descriptors */
  79. Boolean printOnly = FALSE;    /* Stop after computing the domain header
  80.                  * and just print it out. No disk writes */
  81. Boolean overlapBlocks = FALSE;    /* Allow filesystem blocks to overlap track
  82.                  * boundaries.  Some disk systems can't deal. */
  83. char *deviceName;        /* Set to "rsd0" or "rxy1", etc. */
  84. char *partName;            /* Set to "a", "b", "c" ... "g" */
  85. char defaultFirstPartName[] = "a";
  86. char *diskType = NULL;        /* Type of disk (e.g. rz23) */
  87. int  spriteID = 1;        /* This machines sprite id. */
  88. char *devFileName = NULL;    /* Name of file that contains devices to 
  89.                  * create. */
  90. char *dirName = NULL;        /* Name of directory that contains files to
  91.                  * copy to the disk. */
  92. Boolean newLabel = FALSE;
  93.  
  94. Option optionArray[] = {
  95.     {OPT_STRING, "dev", (Address)&deviceName,
  96.     "Required: Name of device, eg \"rsd0\" or \"rxy1\""},
  97.     {OPT_STRING, "part", (Address)&partName,
  98.     "Required: Partition ID: (a, b, c, d, e, f, g)"},
  99.     {OPT_TRUE, "overlap", (Address)&overlapBlocks,
  100.     "Overlap filesystem blocks across track boundaries (FALSE)"},
  101.     {OPT_INT, "ratio", (Address)&kbytesToFileDesc,
  102.     "Ratio of Kbytes to file descriptors (4)"},
  103.     {OPT_TRUE, "test", (Address)&printOnly,
  104.     "Test: print results, don't write disk (FALSE)"},
  105.     {OPT_FALSE, "write", (Address)&printOnly,
  106.     "Write the disk (TRUE)"},
  107.     {OPT_STRING, "type", (Address)&diskType,
  108.     "Type of disk.  Used to look up disk info in /etc/disktab"},
  109.     {OPT_INT, "sid", (Address)&spriteID,
  110.     "Sprite ID of this workstation"},
  111.     {OPT_STRING, "dir", (Address)&dirName,
  112.     "Directory to copy files from"},
  113.     {OPT_STRING, "devFile", (Address)&devFileName,
  114.     "File that contains devices to create"},
  115.     {OPT_TRUE, "newLabel", (Address)&newLabel,
  116.     "Overwrite the current label on the disk if there is one"},
  117. };
  118. int numOptions = sizeof(optionArray) / sizeof(Option);
  119.  
  120. /*
  121.  * Structure used to peruse Sprite directories.
  122.  */
  123. typedef struct DirIndexInfo {
  124.     Fsdm_FileDescriptor *fdPtr;                  /* The file descriptor being
  125.                           * read. */
  126.     int         blockNum;             /* Block that is being read, 
  127.                           * written, or allocated. */
  128.     int         blockAddr;             /* Address of directory block
  129.                           * to read. */
  130.     int         dirOffset;             /* Offset of the directory entry 
  131.                           * that we are currently examining 
  132.                           * in the directory. */
  133.     char     dirBlock[FS_BLOCK_SIZE];    /* Where directory data is 
  134.                           * stored. */
  135. } DirIndexInfo;
  136.  
  137. /*
  138.  * Time of day when this program runs.
  139.  */
  140.  
  141. struct timeval curTime;
  142.  
  143. /*
  144.  * Forward Declarations.
  145.  */
  146. void        SetSummaryInfo();
  147. void        SetDomainHeader();
  148. void        SetDiskGeometry();
  149. void        SetDomainParts();
  150. void        WriteAllFileDescs();
  151. void        WriteAndInitDataBitmap();
  152. unsigned char    *ReadFileDescBitmap();
  153. void        WriteFileDescBitmap();
  154. unsigned char    *ReadBitmap();
  155. void        WriteBitmap();
  156. char         *MakeFileDescBitmap();
  157. Disk_Info    *ScanDiskTab();
  158. static Fslcl_DirEntry    *OpenDir();
  159. Fslcl_DirEntry    *NextDirEntry();
  160. static void        CloseDir();
  161. Fslcl_DirEntry    *AddToDirectory();
  162. void        CreateDir();
  163. void        MarkDataBitmap();
  164. void        InitDesc();
  165. void        CopyTree();
  166. void        ReadFileDesc();
  167. void        WriteFileDesc();
  168. void        MakeDevices();
  169. void        WriteRootDirectory();
  170.  
  171. /*
  172.  * Macro to get a pointer into the bit map for a particular block.
  173.  */
  174. #define BlockToCylinder(domainPtr, blockNum) \
  175.     (blockNum) / (domainPtr)->geometry.blocksPerCylinder
  176.  
  177. #define GetBitmapPtr(domainPtr, bitmapPtr, blockNum) \
  178.   &((bitmapPtr)[BlockToCylinder(domainPtr, blockNum) * \
  179.   bytesPerCylinder + (blockNum) % (domainPtr)->geometry.blocksPerCylinder / 2])
  180.  
  181. /*
  182.  * Macros to convert physical block numbers to virtual block numbers. All direct
  183.  * blocks are virtual, indirect blocks are physical.
  184.  */
  185. #define VirtToPhys(blockNum) \
  186.     ((blockNum) + (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
  187.  
  188. #define PhysToVirt(domainPtr,blockNum) \
  189.     ((blockNum) - (domainPtr)->dataOffset * FS_FRAGMENTS_PER_BLOCK)
  190.  
  191. /*
  192.  * Macro to mark the file descriptor bit map.
  193.  */
  194. #define MarkFDBitmap(num,bitmapPtr) \
  195.     (bitmapPtr)[(num) >> 3] |= (1 << (7 -((num)  & 7)))
  196.  
  197. int            freeFDNum;    /* The currently free file descriptor.*/
  198. int            freeBlockNum;    /* The currently free data block. */
  199. Fsdm_FileDescriptor    devFD;        /* The file descriptor for the dev
  200.                          * directory. */
  201. Fsdm_FileDescriptor    *devFDPtr;    /* Pointer to the file descriptor for
  202.                      * the dev directory. */
  203. int            devFDNum;    /* The file number of the dev 
  204.                      * directory. */
  205. int            partFID;    /* The file id of the partition that
  206.                      * we are initializing. */
  207. Fsdm_DomainHeader         *domainPtr;    /* The domain the we are initializing.*/
  208. int            partition;    /* The partition that we are 
  209.                      * initializing. */
  210. Disk_Info        *diskInfoPtr;    /* Information about the disk that
  211.                      * we are initializing. */
  212. Fsdm_SummaryInfo         *summaryPtr;    /* Summary information for the domain.*/
  213. unsigned char        *fdBitmapPtr;    /* Pointer to the file descriptor
  214.                      * bitmap. */
  215. unsigned char        *cylBitmapPtr;    /* Pointer to the cylinder bit map. */
  216. int            bytesPerCylinder;/* The number of bytes in
  217.                       * the bitmap for a cylinder.*/
  218.  
  219.  
  220.  
  221. /*
  222.  * Some number of sectors in the root partition must be allocated to the
  223.  * boot program. The default is for the new filesystem to have the same
  224.  * number of boot sectors as the old filesystem. If the disk did not
  225.  * previously have a filesystem, or if the domain header cannot be found,
  226.  * then the following number of boot sectors are allocated. The standard
  227.  * Sun format is for the summary sector to be in sector #17. 16 boot sectors
  228.  * and one disk label fill the first 17 sectors.
  229.  */
  230. int    defaultBootSectors = 16;
  231.  
  232. int bootSectors = -1;
  233.  
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * main --
  239.  *
  240.  *    Create the required file names from the command line
  241.  *    arguments.  Then open the first partition on the disk
  242.  *    because it contains the disk label, and open the partition
  243.  *    that is to be formatted.
  244.  *
  245.  * Results:
  246.  *    None.
  247.  *
  248.  * Side effects:
  249.  *    Calls MakeFilesystem
  250.  *
  251.  *----------------------------------------------------------------------
  252.  */
  253. main(argc, argv)
  254.     int        argc;
  255.     char    *argv[];
  256. {
  257.     char    answer[10];
  258.     char    partitionName[64];
  259.     int        status;
  260.     static      char block[DEV_BYTES_PER_SECTOR];
  261.     int         i;
  262.  
  263.     gettimeofday(&curTime, NULL);
  264.  
  265.     (void)Opt_Parse(argc, argv, optionArray, numOptions, 0);
  266.  
  267.     if (deviceName == (char *)0) {
  268.     fprintf(stderr,"Specify device name with -dev option\n");
  269.     exit(1);
  270.     }
  271.     if (partName == (char *)0) {
  272.     fprintf(stderr,"Specify partition with -part option\n");
  273.     exit(1);
  274.     } 
  275.     if (spriteID == 0) {
  276.     fprintf(stderr, "Specify sprite id with -sid option\n");
  277.     exit(1);
  278.     }
  279.  
  280.     bootSectors = defaultBootSectors;
  281.  
  282.     if (!printOnly) {
  283.     printf("The \"-write\" option will cause fsmake to overwrite the current filesystem.\nDo you really want to do this?[y/n] ");
  284.     if (scanf("%10s",answer) != 1) {
  285.         exit(0);
  286.     }
  287.     if ((*answer != 'y') && (*answer != 'Y')) {
  288.         exit(0);
  289.     }
  290.     }
  291.  
  292.     if (partName[0] != 'a' && partName[0] != 'c') {
  293.     fprintf(stderr, "Can only format partitions a or c\n");
  294.     exit(1);
  295.     }
  296.  
  297.     /*
  298.      * Gen up the name of the first partition on the disk.
  299.      */
  300.     sprintf(partitionName, "/dev/%s%s", deviceName, partName);
  301.  
  302.     if (printOnly) {
  303.     partFID = open(partitionName, O_RDONLY);
  304.     } else {
  305.     partFID = open(partitionName, O_RDWR);
  306.     }
  307.     if (partFID < 0 ) {
  308.     perror("Can't open first partition");
  309.     exit(1);
  310.     }
  311.  
  312.     printf("fsmake based on 4K filesystem blocks\n");
  313.  
  314.     partition = partName[0] - 'a';
  315.  
  316.     diskInfoPtr = NULL;
  317.     if (!newLabel) {
  318.     /*
  319.      * See if we can read the copy of the super block at the beginning
  320.      * of the partition to find out basic disk geometry and where to
  321.      * write the domain header.  This will only work with disks that
  322.      * have either a sun label or a sprite label.
  323.      */
  324.     diskInfoPtr = Disk_ReadDiskInfo(partFID, partition);
  325.     }
  326.     if (diskInfoPtr == NULL && diskType != NULL) {
  327.     /*
  328.      * See if we can find the information in /etc/disktab.
  329.      */
  330.     diskInfoPtr = ScanDiskTab();
  331.     }
  332.     if (diskInfoPtr == NULL) {
  333.     fprintf(stderr,"MakeFilesystem: Unable to read super block.\n");
  334.     return(1);
  335.     }
  336.  
  337.     /*
  338.      * Clear out the old summary sector and domain header. This is especially
  339.      * important if we are going to move them.
  340.      */
  341.     if ((!printOnly) && (diskInfoPtr->summarySector != -1)) {
  342.     status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector,1, block);
  343.     if (status != SUCCESS) {
  344.         perror("Clear of old summary sector failed"); 
  345.         return(status);
  346.     }
  347.     for (i = 0; i < diskInfoPtr->numDomainSectors; i++) {
  348.         status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector+i,
  349.                 1, block);
  350.         if (status != SUCCESS) {
  351.         perror("Clear of old domain header failed"); 
  352.         return(status);
  353.         }
  354.     }
  355.     }
  356.     /* 
  357.      * The disk did not previously have a filesystem on it.
  358.      */
  359.     if (diskInfoPtr->summarySector == -1) {
  360.     diskInfoPtr->summarySector = bootSectors + 1;
  361.     diskInfoPtr->domainSector = bootSectors + 2;
  362.     }
  363.     domainPtr = (Fsdm_DomainHeader *)
  364.     malloc((unsigned) diskInfoPtr->numDomainSectors * DEV_BYTES_PER_SECTOR);
  365.     SetDomainHeader();
  366.     bytesPerCylinder = (domainPtr->geometry.blocksPerCylinder + 1) / 2;
  367.     Disk_PrintDomainHeader(domainPtr);
  368.  
  369.     if (!printOnly) {
  370.     assert(diskInfoPtr->domainSector >= 0);
  371.     status = Disk_SectorWrite(partFID, diskInfoPtr->domainSector,
  372.                 diskInfoPtr->numDomainSectors, (Address)domainPtr);
  373.     if (status != 0) {
  374.         perror("DomainHeader write failed");
  375.         return(status);
  376.     }
  377.     }
  378.  
  379.     summaryPtr = (Fsdm_SummaryInfo *) malloc(DEV_BYTES_PER_SECTOR);
  380.     SetSummaryInfo();
  381.     Disk_PrintSummaryInfo(summaryPtr);
  382.     if (!printOnly) {
  383.     assert(diskInfoPtr->summarySector >= 0);
  384.     status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
  385.                 (Address)summaryPtr);
  386.     if (status != 0) {
  387.         perror("Summary sector write failed");
  388.         return(status);
  389.     }
  390.     }
  391.  
  392.     WriteAllFileDescs();
  393.     WriteAndInitDataBitmap();
  394.     WriteRootDirectory();
  395.  
  396.     /*
  397.      * We now have a good empty file system.  Add any files and devices
  398.      * that need to be added.
  399.      */
  400.     if (dirName != NULL) {
  401.     Fsdm_FileDescriptor    rootDesc;
  402.  
  403.     fdBitmapPtr = ReadFileDescBitmap();
  404.     freeFDNum = 3;
  405.     cylBitmapPtr = ReadBitmap();
  406.     freeBlockNum = 1;
  407.     ReadFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
  408.     CopyTree(dirName, FSDM_ROOT_FILE_NUMBER, &rootDesc,
  409.         FSDM_ROOT_FILE_NUMBER, FALSE, "/", 0, 0);
  410.     WriteFileDesc(FSDM_ROOT_FILE_NUMBER, &rootDesc);
  411.     if (devFileName != NULL) {
  412.         if (devFDPtr == NULL) {
  413.         fprintf(stderr, "Couldn't find /dev\n");
  414.         exit(1);
  415.         }
  416.         MakeDevices();
  417.     }
  418.     if (!printOnly) {
  419.         assert(diskInfoPtr->summarySector);
  420.         status = Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1,
  421.                 (Address)summaryPtr);
  422.         if (status != 0) {
  423.         perror("Summary sector write failed (2)");
  424.         exit(status);
  425.         }
  426.         WriteFileDescBitmap(fdBitmapPtr);
  427.         WriteBitmap(cylBitmapPtr);
  428.     }
  429.     }
  430.  
  431.     fflush(stderr);
  432.     fflush(stdout);
  433.     (void)close(partFID);
  434.     exit(0);
  435. }
  436.  
  437.  
  438. /*
  439.  *----------------------------------------------------------------------
  440.  *
  441.  * SetDomainHeader --
  442.  *
  443.  *    Compute the domain header based on the partition size and
  444.  *    other basic disk parameters.
  445.  *
  446.  * Results:
  447.  *    A return code.
  448.  *
  449.  * Side effects:
  450.  *    Fill in the domain header.
  451.  *
  452.  *----------------------------------------------------------------------
  453.  */
  454. void
  455. SetDomainHeader()
  456. {
  457.     register Fsdm_Geometry *geoPtr;
  458.  
  459.     domainPtr->magic = FSDM_DOMAIN_MAGIC;
  460.     domainPtr->firstCylinder = diskInfoPtr->firstCylinder;
  461.     domainPtr->numCylinders = diskInfoPtr->numCylinders;
  462.     /*
  463.      * The device.serverID from the disk is used during boot to discover
  464.      * the host"s spriteID if reverse arp couldn't find a host ID.  The
  465.      * unit number of disk indicates what partition of the disk this
  466.      * domain header applies to.  For example, both the "a" and "c" partitions
  467.      * typically start at sector zero, but only one is valid.  During boot
  468.      * time the unit number is used to decide which partition should be
  469.      * attached.
  470.      */
  471.     domainPtr->device.serverID = spriteID;
  472.     domainPtr->device.type = -1;
  473.     domainPtr->device.unit = partition;
  474.     domainPtr->device.data = (ClientData)-1;
  475.  
  476.     geoPtr = &domainPtr->geometry;
  477.     SetDiskGeometry(&domainPtr->geometry);
  478.  
  479.     SetDomainParts();
  480. }
  481.  
  482. /*
  483.  *----------------------------------------------------------------------
  484.  *
  485.  * SetDiskGeometry --
  486.  *
  487.  *    This computes the rotational set arrangment depending on the
  488.  *    disk geometry.  The basic rules for this are that filesystem blocks
  489.  *    are skewed on successive tracks, and that the skewing pattern
  490.  *    repeats in either 2 or 4 tracks.  This is specific to the fact that
  491.  *    filesystem blocks are 4Kbytes.  This means that one disk track
  492.  *    contains N/4 filesystem blocks and that one sector per track
  493.  *    is wasted if there are an odd number of sectors per track.
  494.  *
  495.  * Results:
  496.  *    None.
  497.  *
  498.  * Side effects:
  499.  *    Fill in the geometry struct.
  500.  *
  501.  *----------------------------------------------------------------------
  502.  */
  503. void
  504. SetDiskGeometry(geoPtr)
  505.     register Fsdm_Geometry    *geoPtr;    /* Fancy geometry information */
  506. {
  507.     int index;            /* Array index */
  508.     int numBlocks;        /* The number of blocks in a rotational set */
  509.     int tracksPerSet;        /* Total number of tracks in a rotational set */
  510.     int numTracks;        /* The number of tracks in the set so far */
  511.     int extraSectors;        /* The number of leftover sectors in a track */
  512.     int offset;            /* The sector offset within a track */
  513.     int startingOffset;        /* The offset of the first block in a track */
  514.     int offsetIncrement;    /* The skew of the starting offset on each
  515.                  * successive track of the rotational set */
  516.     Boolean overlap;        /* TRUE if filesystem blocks overlap tracks */
  517.  
  518.     geoPtr->numHeads = diskInfoPtr->numHeads;
  519.     geoPtr->sectorsPerTrack = diskInfoPtr->numSectors;
  520.  
  521.     /*
  522.      * Figure out some basic parameters of the rotational set.  The number
  523.      * of tracks in the set is either 2 or 4.  If 2, then the blocks on
  524.      * successive tracks are skewed by 1/2 a filesystem block.  If 4,
  525.      * blocks are skewed by 1/4 block.  A 4 track rotational set is best
  526.      * becasue there are more rotational positions.  If, however, it
  527.      * causes 2 or 3 wasted tracks at the end, or if blocks naturally
  528.      * overlap by 1/2 block, then only 2 tracks per rotational set are
  529.      * used.
  530.      */
  531.     switch(geoPtr->numHeads % 4) {
  532.     case 0:
  533.     case 1: {
  534.         extraSectors = geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK;
  535.         if (extraSectors < DISK_SECTORS_PER_BLOCK/4) {
  536.         /*
  537.          * Not enough extra sectors to overlap blocks onto the
  538.          * next track.  The blocks will fit evenly on a track,
  539.          * but the blocks on the following tracks will be skewed.
  540.          */
  541.         tracksPerSet = 4;
  542.         overlap = FALSE;
  543.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  544.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK/2) {
  545.         /*
  546.          * Enough to overlap the first 1/4 block onto the next track.
  547.          */
  548.         tracksPerSet = 4;
  549.         overlap = TRUE;
  550.         offsetIncrement = DISK_SECTORS_PER_BLOCK * 3/4;
  551.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK * 3/4) {
  552.         /*
  553.          * Enough to overlap 1/2 block.
  554.          */
  555.         tracksPerSet = 2;
  556.         overlap = TRUE;
  557.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  558.         } else {
  559.         /*
  560.          * Enough to overlap 3/4 block.
  561.          */
  562.         tracksPerSet = 4;
  563.         overlap = TRUE;
  564.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  565.         }
  566.         break;
  567.     }
  568.     case 2:
  569.     case 3: {
  570.         /*
  571.          * Instead of wasting 2 or 3 tracks to have a 4 track rotational
  572.          * set, the rotational set is only 2 tracks long.  Also see if
  573.          * the blocks naturally overlap by 1/2 block.
  574.          */
  575.         tracksPerSet = 2;
  576.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  577.         if ((geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK) <
  578.               DISK_SECTORS_PER_BLOCK/2) {
  579.         overlap = FALSE;
  580.         } else {
  581.         overlap = TRUE;
  582.         }
  583.     }
  584.     }
  585.     if (!overlapBlocks) {
  586.     overlap = FALSE;
  587.     offsetIncrement = 0;
  588.     }
  589.     printf("overlap %s, offsetIncrement %d\n", (overlap ? "TRUE" : "FALSE"),
  590.               offsetIncrement);
  591.     /*
  592.      * Determine rotational position of the blocks in the rotational set.
  593.      */
  594.     extraSectors = geoPtr->sectorsPerTrack;
  595.     startingOffset = 0;
  596.     offset = startingOffset;
  597.     for (numBlocks = 0, numTracks = 0 ; ; ) {
  598.     if (extraSectors >= DISK_SECTORS_PER_BLOCK) {
  599.         /*
  600.          * Ok to fit in another filesystem block on this track.
  601.          */
  602.         geoPtr->blockOffset[numBlocks] = offset;
  603.         numBlocks++;    
  604.         offset += DISK_SECTORS_PER_BLOCK;
  605.         extraSectors -= DISK_SECTORS_PER_BLOCK;
  606.     } else {
  607.         /*
  608.          * The current block has to take up room on the next track.
  609.          */
  610.         numTracks++;
  611.         if (numTracks < tracksPerSet) {
  612.         /*
  613.          * Ok to go to the next track.
  614.          */
  615.         startingOffset += offsetIncrement;
  616.         if (overlap) {
  617.             /*
  618.              * If the current block can overlap to the next track,
  619.              * use the current offset.  Because of the overlap
  620.              * there are fewer sectors available for blocks on
  621.              * the next track.
  622.              */
  623.             geoPtr->blockOffset[numBlocks] = offset;
  624.             numBlocks++;
  625.             extraSectors = geoPtr->sectorsPerTrack - startingOffset;
  626.         }
  627.         offset = startingOffset + numTracks * geoPtr->sectorsPerTrack;
  628.         if (!overlap) {
  629.             /*
  630.              * If no overlap the whole next track is available.
  631.              */
  632.             extraSectors = geoPtr->sectorsPerTrack;
  633.         }
  634.         } else {
  635.         /*
  636.          * Done.
  637.          */
  638.         for (index = numBlocks; index < FSDM_MAX_ROT_POSITIONS; index++){
  639.             geoPtr->blockOffset[index] = -1;
  640.         }
  641.         break;
  642.         }
  643.     }
  644.     }
  645.     geoPtr->blocksPerRotSet = numBlocks;
  646.     geoPtr->tracksPerRotSet = tracksPerSet;
  647.     geoPtr->rotSetsPerCyl = geoPtr->numHeads / tracksPerSet;
  648.     geoPtr->blocksPerCylinder = numBlocks * geoPtr->rotSetsPerCyl;
  649.  
  650.     /*
  651.      * Now the rotational positions have to be sorted so that rotationally
  652.      * optimal blocks can be found.  The array sortedOffsets is set so
  653.      * that the I'th element has the index into blockOffset which contains
  654.      * the I'th rotational position, eg.
  655.      *    blockOffset    sortedOffsets
  656.      *        0 (+0)        0
  657.      *        8 (+0)        2
  658.      *        4 (+17)        1
  659.      *       12 (+17)        3
  660.      */
  661.  
  662.     offsetIncrement = DISK_SECTORS_PER_BLOCK / tracksPerSet;
  663.     for (index = 0 ; index < FSDM_MAX_ROT_POSITIONS ; index++) {
  664.     geoPtr->sortedOffsets[index] = -1;
  665.     }
  666.     for (index = 0 ; index < numBlocks ; index++) {
  667.     offset = geoPtr->blockOffset[index] % geoPtr->sectorsPerTrack;
  668.     geoPtr->sortedOffsets[offset/offsetIncrement] = index;
  669.     }
  670. }
  671.  
  672. /*
  673.  *----------------------------------------------------------------------
  674.  *
  675.  * SetDomainParts --
  676.  *
  677.  *    Set up the way the domain is divided into 4 areas:  the bitmap
  678.  *    for the file descriptors, the file descriptors, the bitmap for
  679.  *    the data blocks, and the data blocks.
  680.  *
  681.  * Results:
  682.  *    The geometry information is completed.
  683.  *
  684.  * Side effects:
  685.  *    None.
  686.  *
  687.  *----------------------------------------------------------------------
  688.  */
  689. void
  690. SetDomainParts()
  691. {
  692.     register Fsdm_Geometry *geoPtr;
  693.     int            numFiles;
  694.     int         numBlocks;
  695.     int         offset;    
  696.     int         numSectors;
  697.     int            numSets;
  698.     int         bitmapBytes;
  699.  
  700.     /*
  701.      * Set aside a number of blocks at the begining of the partition for
  702.      * things like the super block, the boot program, and the domain header.
  703.      * It is easiest to do this by reserving one or more rotational sets.
  704.      */
  705.     geoPtr = &domainPtr->geometry;
  706.     numSectors = geoPtr->tracksPerRotSet * geoPtr->sectorsPerTrack;
  707.     for ( numSets = 1; ; numSets++ ) {
  708.     if (numSets * numSectors >
  709.         diskInfoPtr->domainSector + diskInfoPtr->numDomainSectors) {
  710.         break;
  711.     }
  712.     }
  713.     printf("Reserving %d blocks for domain header, etc.\n",
  714.             numSets*geoPtr->blocksPerRotSet);
  715.     /*
  716.      * Determine the number of filesystem blocks available and compute a
  717.      * first guess at the number of file descriptors.  If at the end of
  718.      * the computation things don't fit nicely, then the number of files
  719.      * is changed and the computation is repeated.
  720.      */
  721.     numFiles = 0;
  722.     do {
  723.     numBlocks = geoPtr->blocksPerCylinder * diskInfoPtr->numCylinders -
  724.             numSets * geoPtr->blocksPerRotSet;
  725.     if (numFiles == 0) {
  726.         numFiles = numBlocks * DISK_KBYTES_PER_BLOCK / kbytesToFileDesc;
  727.     }
  728.     numFiles          &= ~(FSDM_FILE_DESC_PER_BLOCK-1);
  729.     offset              = numSets * geoPtr->blocksPerRotSet;
  730.  
  731.     domainPtr->fdBitmapOffset = offset;
  732.     bitmapBytes          = (numFiles - 1) / BITS_PER_BYTE + 1;
  733.     domainPtr->fdBitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  734.     numBlocks          -= domainPtr->fdBitmapBlocks;
  735.     offset              += domainPtr->fdBitmapBlocks;
  736.  
  737.     domainPtr->fileDescOffset = offset;
  738.     domainPtr->numFileDesc      = numFiles;
  739.     numBlocks          -= numFiles / FSDM_FILE_DESC_PER_BLOCK;
  740.     offset              += numFiles / FSDM_FILE_DESC_PER_BLOCK;
  741.     /*
  742.      * The data blocks will start on a cylinder.  Try the next
  743.      * cylinder boundary after the start of the bitmap.
  744.      */
  745.     domainPtr->bitmapOffset      = offset;
  746.     domainPtr->dataOffset      = ((offset-1) / geoPtr->blocksPerCylinder + 1)
  747.                      * geoPtr->blocksPerCylinder;
  748.     domainPtr->dataBlocks      = domainPtr->numCylinders *
  749.                       geoPtr->blocksPerCylinder -
  750.                       domainPtr->dataOffset;
  751.     bitmapBytes          = (domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK -
  752.                        1) / BITS_PER_BYTE + 1;
  753.     domainPtr->bitmapBlocks      = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  754.     /*
  755.      * Check the size of the bit map against space available for it
  756.      * between the end of the file descriptors and the start of the
  757.      * data blocks.
  758.      */
  759.     if (domainPtr->dataOffset - domainPtr->bitmapOffset <
  760.         domainPtr->bitmapBlocks) {
  761.         int numBlocksNeeded;
  762.         /*
  763.          * Need more blocks to hold the bitmap.  Reduce the number
  764.          * of file descriptors to get the blocks and re-iterate.
  765.          */
  766.         numBlocksNeeded = domainPtr->bitmapBlocks -
  767.         (domainPtr->dataOffset - domainPtr->bitmapOffset);
  768.         numFiles -= numBlocksNeeded * FSDM_FILE_DESC_PER_BLOCK;
  769.     } else if (domainPtr->dataOffset - domainPtr->bitmapOffset >
  770.             domainPtr->bitmapBlocks) {
  771.         int extraBlocks;
  772.         /*
  773.          * There are extra blocks between the end of the file descriptors
  774.          * and the start of the bitmap.  Increase the number of
  775.          * file descriptors and re-iterate.
  776.          */
  777.         extraBlocks = domainPtr->dataOffset - domainPtr->bitmapOffset -
  778.             domainPtr->bitmapBlocks;
  779.         numFiles += extraBlocks * FSDM_FILE_DESC_PER_BLOCK;
  780.     }
  781.     } while (domainPtr->dataOffset - domainPtr->bitmapOffset !=
  782.         domainPtr->bitmapBlocks);
  783.     domainPtr->dataCylinders    = domainPtr->dataBlocks /
  784.                   geoPtr->blocksPerCylinder ;
  785. }
  786.  
  787. /*
  788.  *----------------------------------------------------------------------
  789.  *
  790.  * SetSummaryInfo --
  791.  *
  792.  *    Initialize the summary information for the domain.  It is well
  793.  *    known that this occupies one sector.
  794.  *
  795.  * Results:
  796.  *    A return code.
  797.  *
  798.  * Side effects:
  799.  *    Fill in the summary info.
  800.  *
  801.  *----------------------------------------------------------------------
  802.  */
  803. void
  804. SetSummaryInfo()
  805. {
  806.  
  807.     bzero((Address)summaryPtr, DEV_BYTES_PER_SECTOR);
  808.  
  809.     strcpy(summaryPtr->domainPrefix, "(new domain)");
  810.     /*
  811.      * 4 blocks are already allocated for the root directory.
  812.      */
  813.     summaryPtr->numFreeKbytes = domainPtr->dataBlocks * (FS_BLOCK_SIZE / 1024)
  814.                 - 4;
  815.     /*
  816.      * 3 file descriptors are already used, 0 and 1 are reserved and
  817.      * 2 is for the root.
  818.      */
  819.     summaryPtr->numFreeFileDesc = domainPtr->numFileDesc - 3;
  820.     /*
  821.      * The summary state field is unused.
  822.      */
  823.     summaryPtr->state = 0;
  824.     /*
  825.      * The domain number under which this disk partition is mounted is
  826.      * recorded on disk so servers re-attach disks under the same "name".
  827.      * We set it to the special value so it gets a new number assigned
  828.      * when it is first attached.
  829.      */
  830.     summaryPtr->domainNumber = -1;
  831.     /*
  832.      * The flags field is used to record whether or not the disk has been
  833.      * safely "sync"ed to disk upon shutdown.
  834.      */
  835.     summaryPtr->flags = 0;
  836.     summaryPtr->attachSeconds = 0;
  837.     summaryPtr->detachSeconds = 0;
  838.     summaryPtr->fixCount = 0;
  839. }
  840.  
  841. /*
  842.  *----------------------------------------------------------------------
  843.  *
  844.  * WriteAllFileDescs --
  845.  *
  846.  *    Write out the file descriptor array to disk.
  847.  *
  848.  * Results:
  849.  *    None.
  850.  *
  851.  * Side effects:
  852.  *    None.
  853.  *
  854.  *----------------------------------------------------------------------
  855.  */
  856. void
  857. WriteAllFileDescs()
  858. {
  859.     int                status;
  860.     char            *bitmap;
  861.     char            *block;
  862.     register Fsdm_FileDescriptor    *fileDescPtr;
  863.     register int        index;
  864.  
  865.     bitmap = MakeFileDescBitmap();
  866.     if (!printOnly) {
  867.     status = Disk_BlockWrite(partFID, domainPtr,
  868.                 domainPtr->fdBitmapOffset,
  869.                 domainPtr->fdBitmapBlocks, (Address)bitmap);
  870.     if (status != 0) {
  871.         fprintf(stderr, "WriteAllFileDescs: Could write fd bitmap\n");
  872.         exit(1);
  873.     }
  874.     }
  875.     /*
  876.      * Make the first block of file descriptors.  This contains some
  877.      * canned file descriptors for the root, bad block file, and the
  878.      * lost and found directory.  For (early system) testing an empty file
  879.      * can also be created.
  880.      */
  881.     block = (char *)malloc(FS_BLOCK_SIZE);
  882.     bzero(block, FS_BLOCK_SIZE);
  883.     for (index = 0;
  884.          index < FSDM_FILE_DESC_PER_BLOCK;
  885.      index++ ) {
  886.     fileDescPtr = (Fsdm_FileDescriptor *)((int)block +
  887.                        index * FSDM_MAX_FILE_DESC_SIZE);
  888.     fileDescPtr->magic = FSDM_FD_MAGIC;
  889.     if (index < FSDM_BAD_BLOCK_FILE_NUMBER) {
  890.         fileDescPtr->flags = FSDM_FD_RESERVED;
  891.     } else if (index == FSDM_BAD_BLOCK_FILE_NUMBER) {
  892.         InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, 0, 0, 0700, curTime.tv_sec);
  893.         fileDescPtr->permissions = 0000;
  894.         fileDescPtr->numLinks = 0;
  895.     } else if (index == FSDM_ROOT_FILE_NUMBER) {
  896.         InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 0,
  897.             0, 0755, curTime.tv_sec);
  898.         /*
  899.          * Place the data in the first file system block.
  900.          */
  901.         fileDescPtr->direct[0] = 0;
  902.     } else {
  903.         fileDescPtr->flags = FSDM_FD_FREE;
  904.     }
  905.     }
  906.     if (!printOnly) {
  907.     /*
  908.      * Write out the first, specially hand crafted, block of file
  909.      * descriptors.
  910.      */
  911.     status = Disk_BlockWrite(partFID, domainPtr, 
  912.                  domainPtr->fileDescOffset,
  913.                  1, (Address)block);
  914.     if (status != 0) {
  915.         fprintf(stderr, "WriteAllFileDescs: Couldn't write descriptor\n");
  916.         exit(1);
  917.     }
  918.     /*
  919.      * Redo the block for the remaining file descriptors
  920.      */
  921.     bzero(block, FS_BLOCK_SIZE);
  922.     for (index = 0;
  923.          index < FSDM_FILE_DESC_PER_BLOCK;
  924.          index++ ) {
  925.         fileDescPtr = (Fsdm_FileDescriptor *)((int)block + index *
  926.                            FSDM_MAX_FILE_DESC_SIZE);
  927.         fileDescPtr->magic = FSDM_FD_MAGIC;
  928.         fileDescPtr->flags = FSDM_FD_FREE;
  929.     }
  930.     /*
  931.      * Write out the remaining file descriptors.
  932.      */
  933.     for (index = FSDM_FILE_DESC_PER_BLOCK;
  934.          index < domainPtr->numFileDesc;
  935.          index += FSDM_FILE_DESC_PER_BLOCK) {
  936.         status = Disk_BlockWrite(partFID, domainPtr,
  937.              domainPtr->fileDescOffset + (index/FSDM_FILE_DESC_PER_BLOCK),
  938.              1, (Address)block);
  939.         if (status != 0) {
  940.         fprintf(stderr, 
  941.             "WriteAllFileDescs: Couldn't write descriptor (2)\n");
  942.         exit(1);
  943.         }
  944.     }
  945.     }
  946. }
  947.  
  948.  
  949. /*
  950.  *----------------------------------------------------------------------
  951.  *
  952.  * MakeFileDescBitmap --
  953.  *
  954.  *    Compute out the bitmap for file descriptor array to disk.
  955.  *
  956.  * Results:
  957.  *    None.
  958.  *
  959.  * Side effects:
  960.  *    None.
  961.  *
  962.  *----------------------------------------------------------------------
  963.  */
  964. char *
  965. MakeFileDescBitmap()
  966. {
  967.     register char    *bitmap;
  968.     register int    index;
  969.  
  970.     /*
  971.      * Allocate and initialize the bitmap to all 0"s to mean all free.
  972.      */
  973.     bitmap = (char *)malloc((unsigned) domainPtr->fdBitmapBlocks *
  974.                  FS_BLOCK_SIZE);
  975.     bzero((Address)bitmap, domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  976.  
  977.     /*
  978.      * Reserve file descriptors 0, 1, and 2.  File number 0 is not used at 
  979.      * all in the filesystem.  File number 1 is for the file with bad blocks.
  980.      * File number 2 (FSDM_ROOT_FILE_NUMBER) is the root directory of the domain.
  981.      *
  982.      * IF THIS CHANGES remember to fix SetSummaryInfo
  983.      */
  984.     bitmap[0] |= 0xe0;
  985.  
  986.     /*
  987.      * Set the bits in the map at the end that don't correspond to
  988.      * any existing file descriptors.
  989.      */
  990.     index = domainPtr->numFileDesc / BITS_PER_BYTE;
  991.     if (domainPtr->numFileDesc % BITS_PER_BYTE) {
  992.     register int bitIndex;
  993.     /*
  994.      * Take care the last byte that only has part of its bits set.
  995.      */
  996.     for (bitIndex = domainPtr->numFileDesc % BITS_PER_BYTE;
  997.          bitIndex < BITS_PER_BYTE;
  998.          bitIndex++) {
  999.         bitmap[index] |= 1 << ((BITS_PER_BYTE - 1) - bitIndex);
  1000.     }
  1001.     index++;
  1002.     }
  1003.     for ( ; index < domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE; index++) {
  1004.     bitmap[index] = 0xff;
  1005.     }
  1006.  
  1007.     if (printOnly) {
  1008.     Disk_PrintFileDescBitmap(domainPtr, bitmap);
  1009.     }
  1010.     return(bitmap);
  1011. }
  1012.  
  1013. /*
  1014.  *----------------------------------------------------------------------
  1015.  *
  1016.  * WriteAndInitDataBitmap --
  1017.  *
  1018.  *    Write out the bitmap for the data blocks.  This knows that the
  1019.  *    first 4K is allocated to the root directory.
  1020.  *
  1021.  * Results:
  1022.  *    A return code from the writes.
  1023.  *
  1024.  * Side effects:
  1025.  *    Write the bitmap.
  1026.  *
  1027.  *----------------------------------------------------------------------
  1028.  */
  1029. void
  1030. WriteAndInitDataBitmap()
  1031. {
  1032.     int        status;
  1033.     char    *bitmap;
  1034.     int        kbytesPerCyl;
  1035.     int        bitmapBytesPerCyl;
  1036.     int        index;
  1037.  
  1038.     bitmap = (char *)malloc((unsigned) domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1039.     bzero(bitmap, domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1040.     /*
  1041.      * Set the bit corresponding to the 4K used for the root directory.
  1042.      *   ________
  1043.      *    |0______7|    Bits are numbered like this in a byte.
  1044.      *
  1045.      * IF THIS CHANGES remember to fix SetSummaryInfo()
  1046.      */
  1047.     bitmap[0] |= 0xf0;
  1048.     /*
  1049.      * The bitmap is organized by cylinder.  There are whole number of
  1050.      * bytes in the bitmap for each cylinder.  Each bit in the bitmap
  1051.      * corresponds to 1 kbyte on the disk.
  1052.      */
  1053.     kbytesPerCyl = domainPtr->geometry.blocksPerCylinder * DISK_KBYTES_PER_BLOCK;
  1054.     bitmapBytesPerCyl = (kbytesPerCyl - 1) / BITS_PER_BYTE + 1;
  1055.     if ((kbytesPerCyl % BITS_PER_BYTE) != 0) {
  1056.     /*
  1057.      * There are bits in the last byte of the bitmap for each cylinder
  1058.      * that don't have kbytes behind them.  Set those bits here so
  1059.      * the blocks don't get allocated.
  1060.      */
  1061.     register int extraBits;
  1062.     register int mask;
  1063.  
  1064.     extraBits = kbytesPerCyl % BITS_PER_BYTE;
  1065.     /*
  1066.      * Set up a mask that has the right part filled with 1"s.
  1067.      */
  1068.     mask = 0x0;
  1069.     for ( ; extraBits < BITS_PER_BYTE ; extraBits++) {
  1070.         mask |= 1 << ((BITS_PER_BYTE - 1) - extraBits);
  1071.     }
  1072.     for (index = 0;
  1073.          index < domainPtr->dataBlocks * DISK_KBYTES_PER_BLOCK / BITS_PER_BYTE;
  1074.          index += bitmapBytesPerCyl) {
  1075.         bitmap[index + bitmapBytesPerCyl - 1] |= mask;
  1076.     }
  1077.     }
  1078.     /*
  1079.      * Set the bits in the bitmap that correspond to non-existent cylinders;
  1080.      * the bitmap is allocated a whole number of blocks on the disk
  1081.      * so there are bytes at its end that don't have blocks behind them.
  1082.      */
  1083.  
  1084.     for (index = domainPtr->dataCylinders * bitmapBytesPerCyl;
  1085.      index < domainPtr->bitmapBlocks * FS_BLOCK_SIZE;
  1086.      index++) {
  1087.     bitmap[index] = 0xff;
  1088.     }
  1089.     if (printOnly) {
  1090.     Disk_PrintDataBlockBitmap(domainPtr, bitmap);
  1091.     } else {
  1092.     status = Disk_BlockWrite(partFID, domainPtr, 
  1093.                  domainPtr->bitmapOffset,
  1094.                  domainPtr->bitmapBlocks, (Address)bitmap);
  1095.     if (status != 0) {
  1096.         fprintf(stderr, "WriteAndInitDataBitmap: Couldn't write bitmap\n");
  1097.         exit(status);
  1098.     }
  1099.     }
  1100. }
  1101.  
  1102.  
  1103. /*
  1104.  *----------------------------------------------------------------------
  1105.  *
  1106.  * WriteRootDirectory --
  1107.  *
  1108.  *    Write the data blocks of the root directory.
  1109.  *
  1110.  * Results:
  1111.  *    A return code from the writes.
  1112.  *
  1113.  * Side effects:
  1114.  *    Write the root directory"s data block.
  1115.  *
  1116.  *----------------------------------------------------------------------
  1117.  */
  1118. void
  1119. WriteRootDirectory()
  1120. {
  1121.     int        status;
  1122.     char    *block;
  1123.     Fslcl_DirEntry    *dirEntryPtr;
  1124.     int        offset;
  1125.     int        i;
  1126.  
  1127.     block = (char *)malloc(FS_BLOCK_SIZE);
  1128.     CreateDir(block, FSDM_ROOT_FILE_NUMBER, FSDM_ROOT_FILE_NUMBER);
  1129.  
  1130.     if (printOnly) {
  1131.     printf("Root Directory\n");
  1132.     offset = 0;
  1133.     dirEntryPtr = (Fslcl_DirEntry *)block;
  1134.     Disk_PrintDirEntry(dirEntryPtr);
  1135.     offset += dirEntryPtr->recordLength;
  1136.     dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  1137.     Disk_PrintDirEntry(dirEntryPtr);
  1138.     } else {
  1139.     /*
  1140.      * This write trounces the data beyond the stuff allocated to
  1141.      * the root directory.  Currently this is ok and is done because
  1142.      * BlockWrite writes whole numbers of filesystem blocks.
  1143.      */
  1144.     status = Disk_BlockWrite(partFID, domainPtr,
  1145.                  domainPtr->dataOffset, 1, block);
  1146.     if (status != 0) {
  1147.         fprintf(stderr, "WriteRootDirectory: Couldn't write directory\n");
  1148.         exit(status);
  1149.     }
  1150.     }
  1151. }
  1152.  
  1153. /*
  1154.  * The 8 partitions, a through h.
  1155.  */
  1156. #define    A_PART    0
  1157. #define B_PART    1
  1158. #define C_PART    2
  1159. #define D_PART    3
  1160. #define E_PART    4
  1161. #define F_PART    5
  1162. #define G_PART    6
  1163. #define H_PART    7
  1164.  
  1165. #define    BUF_SIZE    100
  1166.  
  1167. char        buf[BUF_SIZE];
  1168. char        fullBuf[BUF_SIZE];
  1169.  
  1170.  
  1171. /*
  1172.  *----------------------------------------------------------------------
  1173.  *
  1174.  * ScanDiskTab --
  1175.  *
  1176.  *    Initialize the disk info struct by looking up this disk type in
  1177.  *    the disk table.
  1178.  *
  1179.  * Results:
  1180.  *    A pointer to a disk info struct.
  1181.  *
  1182.  * Side effects:
  1183.  *    Disk info struct malloc'd and initialized.  The disk header will be
  1184.  *    written if is successfully set up.
  1185.  *
  1186.  *----------------------------------------------------------------------
  1187.  */
  1188. Disk_Info *
  1189. ScanDiskTab()
  1190. {
  1191.     FILE        *fp;
  1192.     int            len;
  1193.     char        *bufPtr;
  1194.     int            fullBufLen;
  1195.     Fsdm_DiskPartition    partTable[FSDM_NUM_DISK_PARTS];
  1196.     int            i;
  1197.     int            sectorsPerTrack;
  1198.     int            tracksPerCylinder;
  1199.     int            sectorsPerCylinder;
  1200.     int            numCylinders;
  1201.     Disk_Info        *diskInfoPtr;
  1202.  
  1203.  
  1204.     fp = fopen("/etc/disktab", "r");
  1205.     if (fp == NULL) {
  1206.     perror("/etc/disktab");
  1207.     exit(1);
  1208.     }
  1209.     len = strlen(diskType);
  1210.     /*
  1211.      * Scan until we reach a line that contains the disk type in it.
  1212.      */
  1213.     while (fgets(buf, BUF_SIZE, fp) != NULL) {
  1214.     if (strncmp(diskType, buf, len) == 0 &&
  1215.         buf[len] == '|') {
  1216.         /*
  1217.          * We found the disk type.
  1218.          */
  1219.         break;
  1220.     }
  1221.     }
  1222.     if (strncmp(diskType, buf, len) != 0) {
  1223.     fprintf(stderr, "`%s' not in disktab\n", diskType);
  1224.     exit(1);
  1225.     }
  1226.  
  1227.     fullBufLen = 0;
  1228.     /*
  1229.      * Now cram all of the lines that end in "\" together.
  1230.      */
  1231.     while (1) {
  1232.     for (bufPtr = buf; *bufPtr != '\n' && *bufPtr != '\\'; bufPtr++) {
  1233.         if (*bufPtr != ' ' && *bufPtr != '\t') {
  1234.         fullBuf[fullBufLen] = *bufPtr;
  1235.         fullBufLen++;
  1236.         }
  1237.     }
  1238.     if (*bufPtr == '\n') {
  1239.         fullBuf[fullBufLen] = 0;
  1240.         break;
  1241.     }
  1242.     if (fgets(buf, BUF_SIZE, fp) == NULL) {
  1243.         fprintf(stderr, "Premature EOF\n");
  1244.         exit(1);
  1245.     }
  1246.     }
  1247.     /*
  1248.      * Now build up a partition table.
  1249.      */
  1250.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1251.     partTable[i].firstCylinder = 0;
  1252.     partTable[i].numCylinders = 0;
  1253.     }
  1254.     for (bufPtr = fullBuf; *bufPtr != 0; bufPtr++) {
  1255.     int    partition;
  1256.  
  1257.     if (strncmp(bufPtr, ":ns#", 4) == 0) {
  1258.         bufPtr += 4;
  1259.         sscanf(bufPtr, "%d", §orsPerTrack);
  1260.     } else if (strncmp(bufPtr, ":nt#", 4) == 0) {
  1261.         bufPtr += 4;
  1262.         sscanf(bufPtr, "%d", &tracksPerCylinder);
  1263.     } else if (strncmp(bufPtr, ":nc#", 4) == 0) {
  1264.         bufPtr += 4;
  1265.         sscanf(bufPtr, "%d", &numCylinders);
  1266.     } else if (strncmp(bufPtr, ":p", 2) == 0) {
  1267.         /*
  1268.          * Skip past the ":p".
  1269.          */
  1270.         bufPtr += 2;
  1271.         partition = *bufPtr - 'a';
  1272.         /*
  1273.          * Skip past the partition character and the #.
  1274.          */
  1275.         bufPtr += 2;
  1276.         sscanf(bufPtr, "%d", &partTable[partition].numCylinders);
  1277.     }
  1278.     }
  1279.     /*
  1280.      * Now that we've built up the number of cylinders build up the
  1281.      * cylinder offsets.
  1282.      */
  1283.     sectorsPerCylinder = sectorsPerTrack * tracksPerCylinder;
  1284.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1285.     partTable[i].numCylinders /= sectorsPerCylinder;
  1286.     }
  1287.  
  1288.     partTable[A_PART].firstCylinder = 0;
  1289.     partTable[B_PART].firstCylinder = partTable[A_PART].numCylinders;
  1290.     partTable[C_PART].firstCylinder = 0;
  1291.     partTable[D_PART].firstCylinder = partTable[B_PART].firstCylinder + 
  1292.             partTable[B_PART].numCylinders;
  1293.     partTable[E_PART].firstCylinder = partTable[D_PART].firstCylinder + 
  1294.             partTable[D_PART].numCylinders;
  1295.     partTable[F_PART].firstCylinder = partTable[E_PART].firstCylinder + 
  1296.             partTable[E_PART].numCylinders;
  1297.     partTable[F_PART].numCylinders = 
  1298.             numCylinders - (partTable[E_PART].firstCylinder +
  1299.                     partTable[E_PART].numCylinders);
  1300.     partTable[G_PART].firstCylinder = partTable[B_PART].firstCylinder + 
  1301.             partTable[B_PART].numCylinders;
  1302.     partTable[G_PART].numCylinders = 
  1303.             numCylinders - (partTable[B_PART].firstCylinder +
  1304.                     partTable[B_PART].numCylinders);
  1305.  
  1306.     /*
  1307.      * Print out the partition table.
  1308.      */
  1309.     printf("Sectors-per-track:    %d\n", sectorsPerTrack);
  1310.     printf("Tracks-per-cylinder:    %d\n", tracksPerCylinder);
  1311.     printf("Sectors-per-cylinder:    %d\n", sectorsPerCylinder);
  1312.     printf("Num-cylinders:        %d\n\n", numCylinders);
  1313.     printf("Partition    First-Cylinder        Num-Cylinders\n");
  1314.     for (i = 0; i < FSDM_NUM_DISK_PARTS; i++) {
  1315.     printf("%c        %d            %d\n",
  1316.            'a' + i, partTable[i].firstCylinder, 
  1317.            partTable[i].numCylinders);
  1318.     }
  1319.  
  1320.     /*
  1321.      * Set up a disk header and write it to sector 0.
  1322.      */
  1323.  
  1324.     if (!printOnly) {
  1325.     int        *headerPtr;
  1326.     Fsdm_DiskHeader    header;
  1327.     int        checkSum;
  1328.     int        status;
  1329.  
  1330.     bzero(&header, sizeof(header));
  1331.     strcpy(header.asciiLabel, diskType);
  1332.     header.magic = FSDM_DISK_MAGIC;
  1333.     header.numCylinders = numCylinders;
  1334.     header.numAltCylinders = 0;
  1335.     header.numHeads = tracksPerCylinder;
  1336.     header.numSectors = sectorsPerTrack;
  1337.     header.bootSector = 1;
  1338.     header.numBootSectors = 15;
  1339.     header.summarySector = 17;
  1340.     header.domainSector = 18;
  1341.     header.numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
  1342.     header.partition = partition;
  1343.     bcopy(partTable, header.map, sizeof(header.map));
  1344.     /*
  1345.      * Compute the checksum.
  1346.      */
  1347.     header.checkSum = FSDM_DISK_MAGIC;
  1348.     checkSum = 0;
  1349.     for (i = 0, headerPtr = (int *)&header; 
  1350.          i < DEV_BYTES_PER_SECTOR; 
  1351.          i += sizeof(int), headerPtr++) {
  1352.         checkSum ^= *headerPtr;
  1353.     }
  1354.     header.checkSum = checkSum;
  1355.     /*
  1356.      * Recompute the checksum and make sure it matches.
  1357.      */
  1358.     checkSum = 0;
  1359.     for (i = 0, headerPtr = (int *)&header; 
  1360.          i < DEV_BYTES_PER_SECTOR; 
  1361.          i += sizeof(int), headerPtr++) {
  1362.         checkSum ^= *headerPtr;
  1363.     }
  1364.     if (checkSum != FSDM_DISK_MAGIC) {
  1365.         fprintf(stderr, "Bad checksum\n");
  1366.         exit(1);
  1367.     }
  1368.  
  1369.     /*
  1370.      * Write out the disk header.  Unless this is a sun.
  1371.      * On suns the disk label is a special format so the
  1372.      * prom can read it.  So we don't mess with it.
  1373.      */
  1374.  
  1375. #if !defined(sun) && !defined(sun3) && !defined(sun4)
  1376.     status = Disk_SectorWrite(partFID, 0, 1, (Address)&header);
  1377.     if (status != 0) {
  1378.         perror("Couldn't write out the disk header");
  1379.         exit(1);
  1380.     }
  1381. #endif
  1382.  
  1383.     }
  1384.  
  1385.  
  1386.     /*
  1387.      * Allocate, initialize and return the disk info struct.
  1388.      */
  1389.     diskInfoPtr = (Disk_Info *)malloc(sizeof(Disk_Info));
  1390.     (void)strcpy(diskInfoPtr->asciiLabel, diskType);
  1391.     diskInfoPtr->bootSector = 1;
  1392.     diskInfoPtr->numBootSectors = 15;
  1393.     diskInfoPtr->summarySector = 17;
  1394.     diskInfoPtr->domainSector = 18;
  1395.     diskInfoPtr->numDomainSectors = FSDM_NUM_DOMAIN_SECTORS;
  1396.     diskInfoPtr->firstCylinder = partTable[partition].firstCylinder;
  1397.     diskInfoPtr->numCylinders = partTable[partition].numCylinders;
  1398.     diskInfoPtr->numHeads = tracksPerCylinder;
  1399.     diskInfoPtr->numSectors = sectorsPerTrack;
  1400.  
  1401.     return(diskInfoPtr);
  1402. }
  1403.  
  1404.  
  1405. /*
  1406.  *----------------------------------------------------------------------
  1407.  *
  1408.  * ReadFileDescBitmap --
  1409.  *
  1410.  *    Read in the file descriptor bitmap.
  1411.  *
  1412.  * Results:
  1413.  *    A pointer to the file descriptor bit map.
  1414.  *
  1415.  * Side effects:
  1416.  *    Memory allocated for the bit map.
  1417.  *
  1418.  *----------------------------------------------------------------------
  1419.  */
  1420. unsigned char *
  1421. ReadFileDescBitmap()
  1422. {
  1423.     register unsigned char *bitmap;
  1424.  
  1425.     /*
  1426.      * Allocate the bitmap.
  1427.      */
  1428.     bitmap = (unsigned char *)malloc(domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  1429.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
  1430.           domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  1431.     fprintf(stderr, "ReadFileDescBitmap: Read failed");
  1432.     exit(1);
  1433.     }
  1434.     return(bitmap);
  1435. }
  1436.  
  1437.  
  1438. /*
  1439.  *----------------------------------------------------------------------
  1440.  *
  1441.  * WriteFileDescBitmap --
  1442.  *
  1443.  *    Write out the file descriptor bitmap.
  1444.  *
  1445.  * Results:
  1446.  *    None.
  1447.  *
  1448.  * Side effects:
  1449.  *    None.
  1450.  *
  1451.  *----------------------------------------------------------------------
  1452.  */
  1453. void
  1454. WriteFileDescBitmap(bitmap)
  1455.     register unsigned char     *bitmap;    /* Bitmap to write. */
  1456. {
  1457.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  1458.            domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  1459.     fprintf(stderr, "WriteFileDescBitmap: Write failed");
  1460.     exit(1);
  1461.     }
  1462. }
  1463.  
  1464.  
  1465. /*
  1466.  *----------------------------------------------------------------------
  1467.  *
  1468.  * ReadBitmap --
  1469.  *
  1470.  *    Read the bitmap off disk.
  1471.  *
  1472.  * Results:
  1473.  *    A pointer to the bitmap.
  1474.  *
  1475.  * Side effects:
  1476.  *    Memory allocated for the bit map.
  1477.  *
  1478.  *----------------------------------------------------------------------
  1479.  */
  1480. unsigned char *
  1481. ReadBitmap()
  1482. {
  1483.     unsigned char *bitmap;
  1484.  
  1485.     bitmap = (unsigned char *)malloc(domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1486.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
  1487.           domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  1488.     fprintf(stderr, "ReadBitmap: Read failed");
  1489.     exit(1);
  1490.     }
  1491.     return(bitmap);
  1492. }
  1493.  
  1494.  
  1495. /*
  1496.  *----------------------------------------------------------------------
  1497.  *
  1498.  * WriteBitmap --
  1499.  *
  1500.  *    Write the bitmap to disk.
  1501.  *
  1502.  * Results:
  1503.  *    None.
  1504.  *
  1505.  * Side effects:
  1506.  *    None.
  1507.  *
  1508.  *----------------------------------------------------------------------
  1509.  */
  1510. void
  1511. WriteBitmap(bitmap)
  1512.     unsigned char        *bitmap;    /* Bitmap to write. */
  1513. {
  1514.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  1515.            domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  1516.     fprintf(stderr, "WriteBitmap: Write failed");
  1517.     exit(1);
  1518.     }
  1519. }
  1520.  
  1521.  
  1522. /*
  1523.  *----------------------------------------------------------------------
  1524.  *
  1525.  * ReadFileDesc --
  1526.  *
  1527.  *    Return the given file descriptor.
  1528.  *
  1529.  * Results:
  1530.  *    None.
  1531.  *
  1532.  * Side effects:
  1533.  *    The file descriptor struct is filled in.
  1534.  *
  1535.  *----------------------------------------------------------------------
  1536.  */
  1537. void
  1538. ReadFileDesc(fdNum, fdPtr)
  1539.     int            fdNum;
  1540.     Fsdm_FileDescriptor    *fdPtr;
  1541. {
  1542.     static char        block[FS_BLOCK_SIZE];
  1543.     int            blockNum;
  1544.     int            offset;
  1545.  
  1546.     blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  1547.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  1548.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  1549.                (Address) block) < 0) {
  1550.     fprintf(stderr, "ReadFileDesc: Read failed\n");
  1551.     exit(1);
  1552.     }
  1553.     bcopy((Address)&block[offset], (Address)fdPtr, sizeof(Fsdm_FileDescriptor));
  1554. }
  1555.  
  1556.  
  1557. /*
  1558.  *----------------------------------------------------------------------
  1559.  *
  1560.  * WriteFileDesc --
  1561.  *
  1562.  *    Return the given file descriptor.
  1563.  *
  1564.  * Results:
  1565.  *    None.
  1566.  *
  1567.  * Side effects:
  1568.  *    The file descriptor struct is filled in.
  1569.  *
  1570.  *----------------------------------------------------------------------
  1571.  */
  1572. void
  1573. WriteFileDesc(fdNum, fdPtr)
  1574.     int            fdNum;
  1575.     Fsdm_FileDescriptor    *fdPtr;
  1576. {
  1577.     static char        block[FS_BLOCK_SIZE];
  1578.     int            blockNum;
  1579.     int            offset;
  1580.  
  1581.     blockNum = domainPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  1582.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  1583.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  1584.                (Address) block) < 0) {
  1585.     fprintf(stderr, "WriteFileDesc: Read failed\n");
  1586.     exit(1);
  1587.     }
  1588.     bcopy(fdPtr, (Address)&block[offset], sizeof(Fsdm_FileDescriptor));
  1589.     if (Disk_BlockWrite(partFID, domainPtr, blockNum, 1, 
  1590.                (Address) block) < 0) {
  1591.     fprintf(stderr, "WriteFileDesc: Write failed\n");
  1592.     exit(1);
  1593.     }
  1594. }
  1595.  
  1596. char    fileBlock[FS_BLOCK_SIZE];
  1597. char    indirectBlock[FS_BLOCK_SIZE];
  1598. int    *indIndexPtr = (int *)indirectBlock;
  1599.  
  1600.  
  1601. /*
  1602.  *----------------------------------------------------------------------
  1603.  *
  1604.  * CopyTree --
  1605.  *
  1606.  *    Copy the tree of files in the given directory
  1607.  *    the disk table.
  1608.  *
  1609.  * Results:
  1610.  *    A pointer to a disk info struct.
  1611.  *
  1612.  * Side effects:
  1613.  *    Disk info struct malloc'd and initialized.  The disk header will be
  1614.  *    written if is successfully set up.
  1615.  *
  1616.  *----------------------------------------------------------------------
  1617.  */
  1618. void
  1619. CopyTree(dirName, dirFDNum, dirFDPtr, parentFDNum, createDir, path, dxs, dxp)
  1620.     char        *dirName;    /* Name of directory to copy. */
  1621.     int            dirFDNum;    /* File number of directory. */
  1622.     Fsdm_FileDescriptor    *dirFDPtr;    /* File descriptor of directory. */
  1623.     int            parentFDNum;    /* File number of parent. */
  1624.     Boolean        createDir;    /* Should create the directory. */
  1625.     char        *path;
  1626.     Fslcl_DirEntry      *dxs, *dxp;
  1627. {
  1628.     DIR            *unixDirPtr;
  1629.     Fslcl_DirEntry    *unixDirEntPtr;
  1630.     DirIndexInfo    indexInfo;
  1631.     Fslcl_DirEntry    *spriteDirEntPtr;
  1632.     char        fileName[FS_MAX_NAME_LENGTH + 1];
  1633.     int            newFDNum;
  1634.     Fsdm_FileDescriptor    newFD;
  1635.     Fsdm_FileDescriptor    *newFDPtr;
  1636.     struct    stat    statBuf;
  1637.     int            followLinks;
  1638.     char        pathName[1024];
  1639.     DIR                 dirSave;
  1640.     Fslcl_DirEntry      dirEntSave;
  1641.  
  1642. #define CHECK()
  1643. /*    assert(dxs == 0 || memcmp(dxs, dxp, sizeof(*dxp)) == 0);  */
  1644.  
  1645.     CHECK();
  1646.  
  1647.     /*
  1648.      * Get our absolute path name so we can get back if we follow a
  1649.      * symbolic link.
  1650.      */
  1651.     __getwd(pathName, dxs, dxp);
  1652.  
  1653.     CHECK();
  1654.  
  1655.     if (chdir(dirName) < 0) {
  1656.     perror(dirName);
  1657.     exit(1);
  1658.     }
  1659.     CHECK();
  1660.  
  1661.     /*
  1662.      * Get a pointer to the UNIX directory.
  1663.      */
  1664.     unixDirPtr = opendir(".");
  1665.     if (unixDirPtr == NULL) {
  1666.     fprintf(stderr, "Can't open directory %s\n", dirName);
  1667.     exit(1);
  1668.     }
  1669.     /*
  1670.      * Open the Sprite directory.
  1671.      */
  1672.     CHECK();
  1673.     spriteDirEntPtr = OpenDir(dirFDPtr, &indexInfo);
  1674.     if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
  1675.     if (chdir(pathName) < 0) {
  1676.         perror(pathName);
  1677.         exit(1);
  1678.     }
  1679.     }
  1680.     /*
  1681.      * See if there is a "follow.links" file in this directory.  If so
  1682.      * we are supposed to follow symbolic links rather than just copying
  1683.      * the links.
  1684.      */
  1685.     CHECK();
  1686.     if (stat("follow.links", &statBuf) < 0) {
  1687.     followLinks = 0;
  1688.     } else {
  1689.     printf("Following links ...\n");
  1690.     followLinks = 1;
  1691.     }
  1692.     if (createDir) {
  1693.     CreateDir(indexInfo.dirBlock, dirFDNum, parentFDNum);
  1694.     }
  1695.     CHECK();
  1696.  
  1697.     while ((unixDirEntPtr = (Fslcl_DirEntry *)readdir(unixDirPtr)) != NULL) {
  1698.     CHECK();
  1699.     dirSave = *unixDirPtr;
  1700.     dirEntSave = *unixDirEntPtr;
  1701.  
  1702.     if (unixDirEntPtr->nameLength == 1 && 
  1703.         strncmp(unixDirEntPtr->fileName, ".", 1) == 0) {
  1704.         continue;
  1705.     }
  1706.     if (unixDirEntPtr->nameLength == 2 && 
  1707.         strncmp(unixDirEntPtr->fileName, "..", 2) == 0) {
  1708.         continue;
  1709.     }
  1710.     strncpy(fileName, unixDirEntPtr->fileName, unixDirEntPtr->nameLength);
  1711.     fileName[unixDirEntPtr->nameLength] = 0;
  1712.  
  1713.     printf("filename = |%s|\n", fileName);
  1714.  
  1715.     if (followLinks) {
  1716.         if (stat(fileName, &statBuf) < 0) {
  1717.         perror(fileName);
  1718.         exit(1);
  1719.         }
  1720.     } else {
  1721.         if (lstat(fileName, &statBuf) < 0) {
  1722.         fprintf(stderr, "Can't lstat `%s/%s: %s\n",
  1723.             pathName, fileName, strerror(errno));
  1724.         exit(1);
  1725.         }
  1726.     }
  1727.  
  1728. #if 1
  1729.     CHECK();
  1730.  
  1731.     newFDNum = freeFDNum;
  1732.     freeFDNum++;
  1733.     MarkFDBitmap(newFDNum, fdBitmapPtr);
  1734.     summaryPtr->numFreeFileDesc--;
  1735.     /*
  1736.      * Read out the file descriptor being careful to save it around
  1737.      * if we found the /dev descriptor.
  1738.      */
  1739.     if ((strcmp(fileName, "dev") == 0) &&
  1740.         (dirFDNum == FSDM_ROOT_FILE_NUMBER)) {
  1741.         if (!(statBuf.st_mode & S_GFDIR)) {
  1742.         fprintf(stderr, "dev isn't a directory\n");
  1743.         exit(1);
  1744.         }
  1745.         ReadFileDesc(newFDNum, &devFD);
  1746.         newFDPtr = &devFD;
  1747.         devFDNum = newFDNum;
  1748.         devFDPtr = newFDPtr;
  1749.     } else {
  1750.         ReadFileDesc(newFDNum, &newFD);
  1751.         newFDPtr = &newFD;
  1752.     }
  1753.     spriteDirEntPtr = AddToDirectory(&indexInfo, spriteDirEntPtr,
  1754.                      newFDNum, fileName);
  1755.     if (statBuf.st_mode & S_GFDIR) {
  1756.         char    newPath[FS_MAX_NAME_LENGTH];
  1757.  
  1758.         /*
  1759.          * Increment the current directories link count because once
  1760.          * the child gets created it will point to the parent.
  1761.          */
  1762.         dirFDPtr->numLinks++;
  1763.         /*
  1764.          * Allocate the currently free file descriptor to this directory.
  1765.          */
  1766.         InitDesc(newFDPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, 
  1767.              0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
  1768.         /*
  1769.          * Give the directory one full block.  The directory will
  1770.          * be initialized by CopyTree when we call it recursively.
  1771.          */
  1772.         newFDPtr->direct[0] = freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1773.         MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1774.                FS_FRAGMENTS_PER_BLOCK);
  1775.         freeBlockNum++;
  1776.         sprintf(newPath, "%s%s/", path, fileName);
  1777.         printf("Directory: %s\n", newPath);
  1778.         CHECK();
  1779.  
  1780.         assert(memcmp(&dirEntSave, unixDirEntPtr, sizeof(dirEntSave)) == 0);
  1781.         CopyTree(fileName, newFDNum, newFDPtr, dirFDNum, TRUE, newPath,
  1782.         &dirEntSave, unixDirEntPtr);
  1783.  
  1784.         *unixDirEntPtr = dirEntSave;
  1785.         *unixDirPtr = dirSave;
  1786.  
  1787.         CHECK();
  1788. #if 0
  1789.         {
  1790.         assert(dirSave.dd_fd == unixDirPtr->dd_fd);
  1791.         assert(dirSave.dd_loc == unixDirPtr->dd_loc);
  1792.         assert(dirSave.dd_size == unixDirPtr->dd_size);
  1793.         assert(memcmp(dirSave.dd_buf, unixDirPtr->dd_buf,
  1794.             sizeof(dirSave.dd_buf)) == 0);
  1795.         assert(memcmp(&dirEntSave, unixDirEntPtr,
  1796.             sizeof(dirEntSave)) == 0);
  1797.         }
  1798. #endif
  1799.     } else if ((statBuf.st_mode & S_GFMT) == S_GFREG ||
  1800.            (statBuf.st_mode & S_GFMT) == S_GFLNK) {
  1801.         int    fd;
  1802.         int    blockNum;
  1803.         int    toRead;
  1804.         int    len;
  1805.  
  1806.         blockNum = 0;
  1807.         if ((statBuf.st_mode & S_GFMT) == S_GFREG) {
  1808.         printf("File: %s%s\n", path, fileName);
  1809.         InitDesc(newFDPtr, FS_FILE, statBuf.st_size, -1, -1,
  1810.              0, 0, statBuf.st_mode & 07777, statBuf.st_mtime);
  1811.         /*
  1812.          * Copy the file over.
  1813.          */
  1814.         fd = open(fileName, 0);
  1815.         if (fd < 0) {
  1816.             perror(fileName);
  1817.             exit(1);
  1818.         }
  1819.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  1820.         if (len < 0) {
  1821.             perror(fileName);
  1822.             exit(1);
  1823.         }
  1824.         toRead = statBuf.st_size;
  1825.         } else {
  1826.         len = readlink(fileName, fileBlock, FS_BLOCK_SIZE);
  1827.         if (len < 0) {
  1828.             perror(fileName);
  1829.             exit(1);
  1830.         }
  1831.         fileBlock[len] = '\0';
  1832.         InitDesc(newFDPtr, FS_SYMBOLIC_LINK, len + 1, -1, -1, 
  1833.              0, 0, 0777, statBuf.st_mtime);
  1834.         printf("Symbolic link: %s%s -> %s\n", 
  1835.             path, fileName, fileBlock);
  1836.         toRead = len + 1;
  1837.         }
  1838.  
  1839.         while (len > 0) {
  1840.         if (blockNum == FSDM_NUM_DIRECT_BLOCKS) {
  1841.             int    i;
  1842.             int    *intPtr;
  1843.             /*
  1844.              * Must allocate an indirect block.
  1845.              */
  1846.             newFDPtr->indirect[0] =
  1847.             VirtToPhys(freeBlockNum * FS_FRAGMENTS_PER_BLOCK);
  1848.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1849.                    FS_FRAGMENTS_PER_BLOCK);
  1850.             freeBlockNum++;
  1851.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1852.             for (i = 0, intPtr = (int *)indirectBlock; 
  1853.              i < FS_BLOCK_SIZE / sizeof(int); 
  1854.              i++, intPtr++) {
  1855.              *intPtr = FSDM_NIL_INDEX;
  1856.             }
  1857.         }
  1858.         if (blockNum >= FSDM_NUM_DIRECT_BLOCKS) {
  1859.             indIndexPtr[blockNum - FSDM_NUM_DIRECT_BLOCKS] = 
  1860.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1861.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1862.                    FS_FRAGMENTS_PER_BLOCK);
  1863.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1864.         } else {
  1865.             newFDPtr->direct[blockNum] = 
  1866.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  1867.             if (toRead > FS_BLOCK_SIZE) {
  1868.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1869.                        FS_FRAGMENTS_PER_BLOCK);
  1870.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  1871.             } else {
  1872.             MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  1873.                        (toRead - 1) / FS_FRAGMENT_SIZE + 1);
  1874.             summaryPtr->numFreeKbytes -= 
  1875.                     (toRead - 1) / FS_FRAGMENT_SIZE + 1;
  1876.             }
  1877.         }
  1878.         /*
  1879.          * Write the block out to disk.
  1880.          */
  1881.         if (Disk_BlockWrite(partFID, domainPtr, 
  1882.                     domainPtr->dataOffset + freeBlockNum,
  1883.                     1, (Address)fileBlock) != 0) {
  1884.             fprintf(stderr, "Couldn't write file block\n");
  1885.             exit(1);
  1886.         }
  1887.         blockNum++;
  1888.         freeBlockNum++;
  1889.         if ((statBuf.st_mode & S_GFMT) == S_GFLNK) {
  1890.             break;
  1891.         }
  1892.         toRead -= len;
  1893.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  1894.         if (len < 0) {
  1895.             perror(fileName);
  1896.             exit(1);
  1897.         }
  1898.         }
  1899.         if (newFDPtr->indirect[0] != FSDM_NIL_INDEX) {
  1900.         if (Disk_BlockWrite(partFID, domainPtr,
  1901.                 newFDPtr->indirect[0] / FS_FRAGMENTS_PER_BLOCK,
  1902.                 1, (Address)indirectBlock) != 0) {
  1903.             fprintf(stderr, "Couldn't write indirect block\n");
  1904.             exit(1);
  1905.         }
  1906.         }
  1907.         close(fd);
  1908.     } else {
  1909.         fprintf(stderr, "Non file or directory\n");
  1910.         exit(1);
  1911.     }
  1912.     WriteFileDesc(newFDNum, newFDPtr);
  1913.  
  1914.     if (spriteDirEntPtr == (Fslcl_DirEntry *)NULL) {
  1915.         fprintf(stderr, "%s is full\n", dirName);
  1916.         break;
  1917.     }
  1918.  
  1919. #endif    
  1920.     }
  1921.  
  1922.     CloseDir(&indexInfo);
  1923.  
  1924.     if (chdir(pathName) < 0) {
  1925.     perror(pathName);
  1926.     exit(1);
  1927.     }
  1928.     closedir(unixDirPtr);
  1929.     CHECK();
  1930.     return;
  1931. }
  1932.  
  1933.  
  1934. /*
  1935.  *----------------------------------------------------------------------
  1936.  *
  1937.  * OpenDir --
  1938.  *
  1939.  *    Set up the structure to allow moving through the given directory.
  1940.  *
  1941.  * Results:
  1942.  *    None.
  1943.  *
  1944.  * Side effects:
  1945.  *    The index structure is set up and *dirEntryPtrPtr set to point to
  1946.  *    the first directory entry.
  1947.  *
  1948.  *----------------------------------------------------------------------
  1949.  */
  1950. static Fslcl_DirEntry *
  1951. OpenDir(fdPtr, indexInfoPtr)
  1952.     Fsdm_FileDescriptor    *fdPtr;        /* The file descriptor for the
  1953.                      * directory. */
  1954.     DirIndexInfo     *indexInfoPtr;    /* Index info struct */
  1955. {
  1956.     int            fragsToRead;
  1957.  
  1958.     if (fdPtr->lastByte == -1) {
  1959.     /*
  1960.      * Empty directory.
  1961.      */
  1962.     return((Fslcl_DirEntry *) NULL);
  1963.     } else if ((fdPtr->lastByte + 1) % FSLCL_DIR_BLOCK_SIZE != 0) {
  1964.     fprintf(stderr, "Directory not multiple of directory block size.\n");
  1965.     exit(1);
  1966.     } else if (fdPtr->fileType != FS_DIRECTORY) {
  1967.     fprintf(stderr, "OpenDir: Not a directory\n");
  1968.     return((Fslcl_DirEntry *)NULL);
  1969.     }
  1970.  
  1971.     /*
  1972.      * Initialize the index structure.
  1973.      */
  1974.     indexInfoPtr->fdPtr = fdPtr;
  1975.     indexInfoPtr->blockNum = 0;
  1976.     indexInfoPtr->blockAddr = fdPtr->direct[0] / FS_FRAGMENTS_PER_BLOCK + 
  1977.                   domainPtr->dataOffset;
  1978.     /*
  1979.      * Read in the directory block.
  1980.      */
  1981.     if (fdPtr->lastByte != FS_BLOCK_SIZE - 1) {
  1982.     fprintf(stderr, "We created a directory that's not 4K?\n");
  1983.     exit(1);
  1984.     }
  1985.     if (Disk_BlockRead(partFID, domainPtr,
  1986.                indexInfoPtr->blockAddr,
  1987.                1, indexInfoPtr->dirBlock) < 0) {
  1988.     fprintf(stderr, "OpenDir: Read failed block %d\n",
  1989.             indexInfoPtr->blockAddr);
  1990.     exit(1);
  1991.     } 
  1992.     indexInfoPtr->dirOffset = 0;
  1993.     return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
  1994. }
  1995.  
  1996.  
  1997. /*
  1998.  *----------------------------------------------------------------------
  1999.  *
  2000.  * NextDirEntry --
  2001.  *
  2002.  *    Return a pointer to the next directory entry.
  2003.  *
  2004.  * Results:
  2005.  *    None.
  2006.  *
  2007.  * Side effects:
  2008.  *    The index structure is modified and *dirEntryPtrPtr set to point
  2009.  *    to the next directory entry.
  2010.  *
  2011.  *----------------------------------------------------------------------
  2012.  */
  2013. Fslcl_DirEntry *
  2014. NextDirEntry(indexInfoPtr, dirEntryPtr)
  2015.     DirIndexInfo     *indexInfoPtr;
  2016.     Fslcl_DirEntry        *dirEntryPtr;
  2017. {
  2018.     indexInfoPtr->dirOffset += dirEntryPtr->recordLength;
  2019.     if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
  2020.     /*
  2021.      * The next directory entry is in the current block.
  2022.      */
  2023.     return((Fslcl_DirEntry *)
  2024.             &(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]));
  2025.     } else {
  2026.     Fsdm_FileDescriptor    *fdPtr;
  2027.     int            i;
  2028.  
  2029.     printf("Adding new block to directory ...\n");
  2030.  
  2031.     /*
  2032.      * Write out the current block and set up the next one.
  2033.      */
  2034.     if (!printOnly) {
  2035.         if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
  2036.                 1, indexInfoPtr->dirBlock) < 0) {
  2037.         fprintf(stderr, "NextDirEntry: Write failed block %d\n",
  2038.                 indexInfoPtr->blockAddr);
  2039.         exit(1);
  2040.         }
  2041.     }
  2042.     fdPtr = indexInfoPtr->fdPtr;
  2043.     fdPtr->lastByte += FS_BLOCK_SIZE;
  2044.     fdPtr->numKbytes += FS_FRAGMENTS_PER_BLOCK;
  2045.     indexInfoPtr->blockNum++;
  2046.     fdPtr->direct[indexInfoPtr->blockNum] = 
  2047.                 freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  2048.     MarkDataBitmap(domainPtr, cylBitmapPtr, freeBlockNum,
  2049.                FS_FRAGMENTS_PER_BLOCK);
  2050.     indexInfoPtr->blockAddr = freeBlockNum + domainPtr->dataOffset;
  2051.     freeBlockNum++;
  2052.     for (i = 0, dirEntryPtr = (Fslcl_DirEntry *)indexInfoPtr->dirBlock; 
  2053.          i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
  2054.      i++,dirEntryPtr=(Fslcl_DirEntry *)((unsigned)dirEntryPtr+FSLCL_DIR_BLOCK_SIZE)) {
  2055.         dirEntryPtr->fileNumber = 0;
  2056.         dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2057.         dirEntryPtr->nameLength = 0;
  2058.     }
  2059.     indexInfoPtr->dirOffset = 0;
  2060.     return((Fslcl_DirEntry *) indexInfoPtr->dirBlock);
  2061.     }
  2062. }
  2063.  
  2064.  
  2065. /*
  2066.  *----------------------------------------------------------------------
  2067.  *
  2068.  * CloseDir --
  2069.  *
  2070.  *    Flushes the current directory block to disk, if necessary.
  2071.  *
  2072.  * Results:
  2073.  *    None.
  2074.  *
  2075.  * Side effects:
  2076.  *    The index structure is modified and *dirEntryPtrPtr set to point
  2077.  *    to the next directory entry.
  2078.  *
  2079.  *----------------------------------------------------------------------
  2080.  */
  2081. static void
  2082. CloseDir(indexInfoPtr)
  2083.     DirIndexInfo     *indexInfoPtr;
  2084. {
  2085.  
  2086.     if (!printOnly) {
  2087.     if (Disk_BlockWrite(partFID, domainPtr, indexInfoPtr->blockAddr,
  2088.                 1, indexInfoPtr->dirBlock) < 0) {
  2089.         fprintf(stderr, "CloseDir: Write (2) failed block %d\n",
  2090.                 indexInfoPtr->blockAddr);
  2091.         exit(1);
  2092.     }
  2093.     }
  2094. }
  2095.  
  2096.  
  2097. /*
  2098.  *----------------------------------------------------------------------
  2099.  *
  2100.  * InitDesc --
  2101.  *
  2102.  *    Set up a file descriptor as allocated.
  2103.  *
  2104.  * Results:
  2105.  *    None.
  2106.  *
  2107.  * Side effects:
  2108.  *    File descriptor fields filled in.
  2109.  *
  2110.  *----------------------------------------------------------------------
  2111.  */
  2112. void
  2113. InitDesc(fileDescPtr, fileType, numBytes, devType, devUnit, uid,
  2114.     gid, permissions, time)
  2115.     Fsdm_FileDescriptor    *fileDescPtr;
  2116.     int            fileType;
  2117.     int            numBytes;
  2118.     int            devType;
  2119.     int            devUnit;
  2120.     int            uid;
  2121.     int            gid;
  2122.     int            permissions;
  2123.     int            time;
  2124. {
  2125.     int        index;
  2126.  
  2127.     fileDescPtr->flags = FSDM_FD_ALLOC;
  2128.     fileDescPtr->fileType = fileType;
  2129.     fileDescPtr->permissions = permissions;
  2130.     fileDescPtr->uid = uid;
  2131.     fileDescPtr->gid = gid;
  2132.     fileDescPtr->lastByte = numBytes - 1;
  2133.     fileDescPtr->firstByte = -1;
  2134.     if (fileType == FS_DIRECTORY) {
  2135.     fileDescPtr->numLinks = 2;
  2136.     } else {
  2137.     fileDescPtr->numLinks = 1;
  2138.     }
  2139.     /*
  2140.      * Can't know device information because that depends on
  2141.      * the way the system is configured.
  2142.      */
  2143.     fileDescPtr->devServerID = -1;
  2144.     fileDescPtr->devType = devType;
  2145.     fileDescPtr->devUnit = devUnit;
  2146.  
  2147.     /*
  2148.      * Set the time stamps.  This assumes that universal time,
  2149.      * not local time, is used for time stamps.
  2150.      */
  2151.     fileDescPtr->createTime = time;
  2152.     fileDescPtr->accessTime = 0;
  2153.     fileDescPtr->descModifyTime = time;
  2154.     fileDescPtr->dataModifyTime = time;
  2155.  
  2156.     /*
  2157.      * Place the data in the first filesystem block.
  2158.      */
  2159.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  2160.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  2161.     }
  2162.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  2163.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  2164.     }
  2165.     if (numBytes > 0) {
  2166.     int    numBlocks;
  2167.  
  2168.     numBlocks = (numBytes - 1) / FS_BLOCK_SIZE + 1;
  2169.     if (numBlocks > FSDM_NUM_DIRECT_BLOCKS) {
  2170.         fileDescPtr->numKbytes = (numBlocks + 1) * (FS_BLOCK_SIZE / 1024);
  2171.     } else {
  2172.         fileDescPtr->numKbytes = (numBytes + 1023) / 1024;
  2173.     }
  2174.     } else {
  2175.     fileDescPtr->numKbytes = 0;
  2176.     }
  2177.  
  2178.     fileDescPtr->version = 1;
  2179. }
  2180.  
  2181. int fragMasks[FS_FRAGMENTS_PER_BLOCK + 1] = {0x0, 0x08, 0x0c, 0x0e, 0x0f};
  2182.  
  2183.  
  2184. /*
  2185.  *----------------------------------------------------------------------
  2186.  *
  2187.  * MarkDataBitmap --
  2188.  *
  2189.  *    Mark the appropriate bits in the data block bitmap.
  2190.  *
  2191.  * Results:
  2192.  *    None.
  2193.  *
  2194.  * Side effects:
  2195.  *    Data block marked.
  2196.  *
  2197.  *----------------------------------------------------------------------
  2198.  */
  2199. void
  2200. MarkDataBitmap(domainPtr, cylBitmapPtr, blockNum, numFrags)
  2201.     Fsdm_DomainHeader    *domainPtr;
  2202.     unsigned char    *cylBitmapPtr;
  2203.     int            blockNum;
  2204.     int            numFrags;
  2205. {
  2206.     unsigned char    *bitmapPtr;
  2207.  
  2208.     bitmapPtr = GetBitmapPtr(domainPtr, cylBitmapPtr, blockNum);
  2209.     if ((blockNum % domainPtr->geometry.blocksPerCylinder) & 0x1) {
  2210.     *bitmapPtr |= fragMasks[numFrags];
  2211.     } else {
  2212.     *bitmapPtr |= fragMasks[numFrags] << 4;
  2213.     }
  2214. }
  2215.  
  2216.  
  2217.  
  2218. /*
  2219.  *----------------------------------------------------------------------
  2220.  *
  2221.  * CreateDir --
  2222.  *
  2223.  *    Create a directory out of a single file system block.
  2224.  *
  2225.  * Results:
  2226.  *    None.
  2227.  *
  2228.  * Side effects:
  2229.  *    File system block set up as a directory.
  2230.  *
  2231.  *----------------------------------------------------------------------
  2232.  */
  2233. void
  2234. CreateDir(block, dot, dotDot)
  2235.     Address    block;        /* Block to create directory in. */
  2236.     int        dot;        /* File number of directory. */
  2237.     int        dotDot;        /* File number of parent. */
  2238. {
  2239.     Fslcl_DirEntry    *dirEntryPtr;
  2240.     char    *fileName;
  2241.     int        offset;
  2242.     int        length;
  2243.     int        i;
  2244.  
  2245.     dirEntryPtr = (Fslcl_DirEntry *)block;
  2246.     fileName = ".";
  2247.     length = strlen(fileName);
  2248.     dirEntryPtr->fileNumber = dot;
  2249.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  2250.     dirEntryPtr->nameLength = length;
  2251.     strcpy(dirEntryPtr->fileName, fileName);
  2252.     offset = dirEntryPtr->recordLength;
  2253.  
  2254.     dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  2255.     fileName = "..";
  2256.     length = strlen(fileName);
  2257.     dirEntryPtr->fileNumber = dotDot;
  2258.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  2259.     dirEntryPtr->nameLength = length;
  2260.     strcpy(dirEntryPtr->fileName, fileName);
  2261.     /*
  2262.      * Fill out the rest of the directory with empty blocks.
  2263.      */
  2264.     for (dirEntryPtr = (Fslcl_DirEntry *)&block[FSLCL_DIR_BLOCK_SIZE], i = 1; 
  2265.      i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
  2266.      i++,dirEntryPtr=(Fslcl_DirEntry *)((int)dirEntryPtr + FSLCL_DIR_BLOCK_SIZE)) {
  2267.      dirEntryPtr->fileNumber = 0;
  2268.      dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2269.      dirEntryPtr->nameLength = 0;
  2270.     }
  2271. }
  2272.  
  2273.  
  2274. /*
  2275.  *----------------------------------------------------------------------
  2276.  *
  2277.  * AddToDirectory --
  2278.  *
  2279.  *    Add the file descriptor to a directory.  
  2280.  *
  2281.  * Results:
  2282.  *    None.
  2283.  *
  2284.  * Side effects:
  2285.  *    The directory is modified to contain the orphaned file.
  2286.  *
  2287.  *----------------------------------------------------------------------
  2288.  */
  2289. Fslcl_DirEntry *
  2290. AddToDirectory(dirIndexPtr, dirEntryPtr, fileNumber, fileName)
  2291.     DirIndexInfo    *dirIndexPtr;
  2292.     Fslcl_DirEntry        *dirEntryPtr;
  2293.     int             fileNumber;
  2294.     char         *fileName;
  2295. {
  2296.     int             nameLength;
  2297.     int             recordLength;
  2298.     int             leftOver;
  2299.     int            oldRecLength;
  2300.  
  2301.     nameLength = strlen(fileName);
  2302.     recordLength = Fslcl_DirRecLength(nameLength);
  2303.  
  2304.     while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
  2305.     if (dirEntryPtr->fileNumber != 0) {
  2306.         oldRecLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  2307.         leftOver = dirEntryPtr->recordLength - oldRecLength;
  2308.         if (leftOver >= recordLength) {
  2309.         dirEntryPtr->recordLength = oldRecLength;
  2310.         dirEntryPtr = 
  2311.             (Fslcl_DirEntry *) ((int) dirEntryPtr + oldRecLength);
  2312.         dirEntryPtr->recordLength = leftOver;
  2313.         dirIndexPtr->dirOffset += oldRecLength;
  2314.         } else {
  2315.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2316.         continue;
  2317.         }
  2318.     } else if (dirEntryPtr->recordLength < recordLength) {
  2319.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2320.         continue;
  2321.     }
  2322.  
  2323.     dirEntryPtr->fileNumber = fileNumber;
  2324.     dirEntryPtr->nameLength = nameLength;
  2325.     (void)strcpy(dirEntryPtr->fileName, fileName);
  2326.     leftOver = dirEntryPtr->recordLength - recordLength;
  2327.     if (leftOver > FSLCL_DIR_ENTRY_HEADER) {
  2328.         dirEntryPtr->recordLength = recordLength;
  2329.         dirEntryPtr =(Fslcl_DirEntry *) ((int) dirEntryPtr + recordLength);
  2330.         dirEntryPtr->fileNumber = 0;
  2331.         dirEntryPtr->recordLength = leftOver;
  2332.         dirIndexPtr->dirOffset += recordLength;
  2333.     } else {
  2334.         dirEntryPtr = NextDirEntry(dirIndexPtr, dirEntryPtr);
  2335.     }
  2336.     return(dirEntryPtr);
  2337.     }
  2338.  
  2339.     fprintf(stderr, "Directory full.\n");
  2340.     exit(1);
  2341. }
  2342.  
  2343.  
  2344. /*
  2345.  *----------------------------------------------------------------------
  2346.  *
  2347.  * MakeDevices --
  2348.  *
  2349.  *    Add devices to the dev directory.
  2350.  *
  2351.  * Results:
  2352.  *    None.
  2353.  *
  2354.  * Side effects:
  2355.  *    Devices added to the dev directory.
  2356.  *
  2357.  *----------------------------------------------------------------------
  2358.  */
  2359. void
  2360. MakeDevices()
  2361. {
  2362.     FILE        *fp;
  2363.     Fslcl_DirEntry        *dirEntryPtr;
  2364.     DirIndexInfo    indexInfo;
  2365.     char        fileName[FS_MAX_NAME_LENGTH];
  2366.     int            devType;
  2367.     int            devUnit;
  2368.     int            devPermissions;
  2369.     char        buf[FS_MAX_NAME_LENGTH];
  2370.     Fsdm_FileDescriptor    fileFD;
  2371.  
  2372.     fp = fopen(devFileName, "r");
  2373.     if (fp == NULL) {
  2374.     perror(devFileName);
  2375.     exit(1);
  2376.     }
  2377.  
  2378.     dirEntryPtr = OpenDir(devFDPtr, &indexInfo);
  2379.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  2380.     fprintf(stderr, "MakeDevices: Dev is bogus\n");
  2381.     exit(1);
  2382.     }
  2383.     while (fgets(buf, FS_MAX_NAME_LENGTH, fp) != NULL) {
  2384.     if (sscanf(buf, "%s %d %d %o", fileName, &devType, &devUnit,
  2385.         &devPermissions) != 4) {
  2386.         continue;
  2387.     }
  2388.     MarkFDBitmap(freeFDNum, fdBitmapPtr);
  2389.     ReadFileDesc(freeFDNum, &fileFD);
  2390.     InitDesc(&fileFD, FS_DEVICE, 0, devType, devUnit, 0, 0,
  2391.         devPermissions, curTime.tv_sec);
  2392.     dirEntryPtr = AddToDirectory(&indexInfo, dirEntryPtr, freeFDNum,
  2393.                      fileName);
  2394.     if (!printOnly) {
  2395.         WriteFileDesc(freeFDNum, &fileFD);
  2396.     }
  2397.     printf("Device: %s, %d, %d 0%o\n",
  2398.         fileName, devType, devUnit, devPermissions);
  2399.  
  2400.     summaryPtr->numFreeFileDesc--;
  2401.     freeFDNum++;
  2402.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  2403.         fprintf(stderr, "MakeDevices: dev directory is full\n");
  2404.         break;
  2405.     }
  2406.     }
  2407.     CloseDir(&indexInfo);
  2408. }
  2409.  
  2410. #if 0
  2411. /*
  2412.  *----------------------------------------------------------------------
  2413.  *
  2414.  * CopySuperBlock --
  2415.  *
  2416.  *    Copy the super block from the first sector of the disk to
  2417.  *    the first sector of the partition being formatted.
  2418.  *
  2419.  * Results:
  2420.  *    A return code from the I/O.
  2421.  *
  2422.  * Side effects:
  2423.  *    Writes on the zero'th sector of the partition.
  2424.  *
  2425.  *----------------------------------------------------------------------
  2426.  */
  2427. ReturnStatus
  2428. CopySuperBlock(firstPartFID, partFID)
  2429.     int firstPartFID;
  2430.     int partFID;
  2431. {
  2432.     ReturnStatus status;
  2433.     char *block;
  2434.  
  2435.     block = (char *)malloc(DEV_BYTES_PER_SECTOR);
  2436.  
  2437.     status = Disk_SectorRead(firstPartFID, 0, 1, block);
  2438.     if (status != SUCCESS) {
  2439.     return(status);
  2440.     }
  2441.     status = Disk_SectorWrite(partFID, 0, 1, block);
  2442.     return(status);
  2443. }
  2444. #endif
  2445.  
  2446. #define GETWDERR(s)    strcpy(pathname, (s));
  2447.  
  2448. static char *prepend();
  2449.  
  2450. char *strcpy();
  2451. static int pathsize;            /* pathname length */
  2452.  
  2453. static char *oldGetwd();
  2454.  
  2455.  
  2456. DIR *
  2457. __opendir(name, dxs, dxp)
  2458.     char *name;
  2459.     Fslcl_DirEntry      *dxs, *dxp;
  2460. {
  2461.     register DIR *dirp;
  2462.     register int fd;
  2463.  
  2464.     CHECK();
  2465.  
  2466.     if ((fd = open(name, O_RDONLY, 0)) == -1)
  2467.         return NULL;
  2468.  
  2469.     CHECK();
  2470.  
  2471.     if ((dirp = (DIR *)__malloc(sizeof(DIR), dxs, dxp)) == NULL) {
  2472.         close (fd);
  2473.         return NULL;
  2474.     }
  2475.  
  2476.     CHECK();
  2477.  
  2478.     dirp->dd_fd = fd;
  2479.     dirp->dd_loc = 0;
  2480.  
  2481.     CHECK();
  2482.  
  2483.     return dirp;
  2484. }
  2485.  
  2486. char *
  2487. __getwd(pathname, dxs, dxp)
  2488.     char *pathname;
  2489.     Fslcl_DirEntry      *dxs, *dxp;
  2490. {
  2491.     char pathbuf[MAXPATHLEN];        /* temporary pathname buffer */
  2492.     char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
  2493.     char curdir[MAXPATHLEN];        /* current directory buffer */
  2494.     char *dptr = curdir;        /* directory pointer */
  2495.     char *prepend();            /* prepend dirname to pathname */
  2496.     int cdev;                /* current & root device number */
  2497.     int cino;                /* current & root inode number */
  2498.     int curServer;            /* current and root server ID */
  2499.     DIR *dirp;                /* directory stream */
  2500.     struct direct *dir;            /* directory entry struct */
  2501.     Fs_Attributes d;            /* file status struct */
  2502.     int fd;                /* Handle on current directory */
  2503.     Ioc_PrefixArgs iocPrefix;        /* Returned by ioctl. */
  2504.     ReturnStatus status;
  2505.  
  2506.     CHECK();
  2507.     pathsize = 0;
  2508.     *pnptr = '\0';
  2509.     fd = open(".", O_RDONLY);
  2510.     if (fd < 0) {
  2511.     GETWDERR("getwd: can't open .");
  2512.     }
  2513.     status = Fs_IOControl(fd, IOC_PREFIX, 0, NULL, sizeof(Ioc_PrefixArgs), 
  2514.         &iocPrefix);
  2515.     CHECK();
  2516.  
  2517.     if (status != SUCCESS) {
  2518.     /*
  2519.      * If the ioctl fails assume we are on an old kernel and do it the
  2520.      * old way.
  2521.      */
  2522. #if 0
  2523.     printf("Using old getwd -- \"%s\".\n", Stat_GetMsg(status));
  2524.     return oldGetwd(pathname);
  2525. #endif
  2526.     assert(status == SUCCESS);
  2527.     abort();
  2528.     }
  2529.     close(fd);
  2530.     strcpy(dptr, "./");
  2531.     dptr += 2;
  2532.     if (Fs_GetAttributes(curdir, FS_ATTRIB_FILE, &d) != SUCCESS) {
  2533.         GETWDERR("getwd: can't stat .");
  2534.         return (NULL);
  2535.     }
  2536.     CHECK();
  2537.     for (;;) {
  2538.     CHECK();
  2539.     cino = d.fileNumber;
  2540.     cdev = d.domain;
  2541.     curServer = d.serverID;
  2542.     strcpy(dptr, "../");
  2543.     CHECK();
  2544.     dptr += 3;
  2545.     if ((dirp = __opendir(curdir, dxs, dxp)) == NULL) {
  2546.         GETWDERR("getwd: can't open ..");
  2547.         return (NULL);
  2548.     }
  2549.     CHECK();
  2550.     Fs_GetAttributesID(dirp->dd_fd, &d);
  2551.     CHECK();
  2552.     if (curServer == d.serverID && cdev == d.domain) {
  2553.         /*
  2554.          * Parent directory is in the same domain as the current point.
  2555.          * Check against root loop and then scan parent looking for match.
  2556.          */
  2557.         if (cino == d.fileNumber) {
  2558.         /* reached root directory */
  2559.         closedir(dirp);
  2560.         break;
  2561.         }
  2562.         CHECK();
  2563.         do {
  2564.         CHECK();
  2565.         if ((dir = readdir(dirp)) == NULL) {
  2566.             closedir(dirp);
  2567.             GETWDERR("getwd: read error in ..");
  2568.             return (NULL);
  2569.         }
  2570.         } while (dir->d_ino != cino);
  2571.         CHECK();
  2572.         closedir(dirp);
  2573.         CHECK();
  2574.         pnptr = prepend("/", prepend(dir->d_name, pnptr));
  2575.         CHECK();
  2576.     } else {
  2577.         /*
  2578.          * The parent directory is in a different domain.  This means that
  2579.          * the current point should be the root of a domain and this
  2580.          * host should have a prefix that corresponds to it. 
  2581.          * We already have the prefix from the ioctl, so just break.
  2582.          */
  2583.         break;
  2584.     }
  2585.     }
  2586.     CHECK();
  2587.     if ((strcmp(iocPrefix.prefix, "/") != 0) || (*pnptr == 0)) {
  2588.     pnptr = prepend(iocPrefix.prefix, pnptr);
  2589.     }
  2590.     CHECK();
  2591.     strcpy(pathname, pnptr);
  2592.     CHECK();
  2593.     return (pathname);
  2594. }
  2595.  
  2596. /*
  2597.  * prepend() tacks a directory name onto the front of a pathname.
  2598.  */
  2599. static char *
  2600. prepend(dirname, pathname)
  2601.     register char *dirname;
  2602.     register char *pathname;
  2603. {
  2604.     register int i;            /* directory name size counter */
  2605.  
  2606.     for (i = 0; *dirname != '\0'; i++, dirname++)
  2607.         continue;
  2608.     if ((pathsize += i) < MAXPATHLEN)
  2609.         while (i-- > 0)
  2610.             *--pathname = *--dirname;
  2611.     return (pathname);
  2612. }
  2613.  
  2614. char *
  2615. __malloc(bytesNeeded, dxs, dxp)
  2616.     register unsigned bytesNeeded;    /* How many bytes to allocate. */
  2617.     Fslcl_DirEntry      *dxs, *dxp;
  2618. {
  2619.     int            thisBlockSize, admin;
  2620.     register Address    result;
  2621.     Address        newRegion;
  2622.     int            regionSize;
  2623.     int            origSize;
  2624.     register int    index;
  2625.  
  2626.     CHECK();
  2627.  
  2628.     LOCK_MONITOR;
  2629.     CHECK();
  2630.  
  2631. #ifdef MEM_TRACE
  2632.     mem_NumAllocs++;
  2633. #endif
  2634.  
  2635.     if (!memInitialized) {
  2636.     MemInit();
  2637.     }
  2638.     CHECK();
  2639.  
  2640.     origSize = bytesNeeded;
  2641.  
  2642.     /* 
  2643.      * Handle binned objects quickly, if possible.
  2644.      */
  2645.  
  2646.     bytesNeeded = BYTES_TO_BLOCKSIZE(bytesNeeded);
  2647.     index = BLOCKSIZE_TO_INDEX(bytesNeeded);
  2648.     if (bytesNeeded <= BIN_SIZE) {
  2649.     CHECK();
  2650.     result = memFreeLists[index];
  2651.     if (result == NOBIN) {
  2652.         goto largeBlockAllocator;
  2653.     }
  2654.     if (result == (Address) NULL) {
  2655.  
  2656.         CHECK();
  2657.         /*
  2658.          * There aren't currently any free objects of this size.
  2659.          * Call the client's function to obtain another region
  2660.          * from the system.  While we're at it, get a whole bunch
  2661.          * of objects of this size once and put all but one back
  2662.          * on the free list.
  2663.          */
  2664.  
  2665.         regionSize = BLOCKS_AT_ONCE * bytesNeeded;
  2666.         newRegion = MemChunkAlloc(regionSize);
  2667.  
  2668.         while (regionSize >= bytesNeeded) {
  2669.         CHECK();
  2670.  
  2671.         SET_ADMIN(newRegion, memFreeLists[index]);
  2672.         memFreeLists[index] = newRegion;
  2673.         mem_NumBlocks[index] += 1;
  2674.         newRegion += bytesNeeded;
  2675.         regionSize -= bytesNeeded;
  2676.         }
  2677.         result = memFreeLists[index];
  2678.     }
  2679.     CHECK();
  2680.  
  2681.     memFreeLists[index] = (Address) GET_ADMIN(result);
  2682.     SET_ADMIN(result, MARK_DUMMY(bytesNeeded));
  2683.     CHECK();
  2684.  
  2685. #ifdef MEM_TRACE
  2686.     CHECK();
  2687.     mem_NumBinnedAllocs[index] += 1;
  2688.     SET_PC(result);
  2689.     SET_ORIG_SIZE(result, origSize);
  2690.     MemDoTrace(TRUE, result, (Address)NULL, bytesNeeded);
  2691. #endif MEM_TRACE
  2692.     CHECK();
  2693.  
  2694.     UNLOCK_MONITOR;
  2695.     CHECK();
  2696.     return(result+sizeof(AdminInfo));
  2697.     }
  2698.  
  2699.     /*
  2700.      * This is a large object.  Step circularly through the blocks
  2701.      * in the list, looking for one that's large enough to hold
  2702.      * what's needed.
  2703.      */
  2704.  
  2705. largeBlockAllocator:
  2706.     if (origSize == 0) {
  2707.     return (Address) NULL;
  2708.     }
  2709.     CHECK();
  2710. #ifdef MEM_TRACE
  2711.     mem_NumLargeAllocs += 1;
  2712. #endif
  2713.     result = memCurrentPtr;
  2714.     CHECK();
  2715.     while (TRUE) {
  2716.     Address nextPtr;
  2717.     CHECK();
  2718.  
  2719. #ifdef MEM_TRACE
  2720.     mem_NumLargeLoops += 1;
  2721. #endif
  2722.     admin = GET_ADMIN(result);
  2723.     thisBlockSize = SIZE(admin);
  2724.     nextPtr = result+thisBlockSize;
  2725.     if (!IS_IN_USE(admin)) {
  2726.  
  2727.     CHECK();
  2728.         /*
  2729.          * Several blocks in a row could have been freed since the last
  2730.          * time we were here.  If so, merge them together.
  2731.          */
  2732.  
  2733.         while (!IS_IN_USE(GET_ADMIN(nextPtr))) {
  2734.         thisBlockSize += SIZE(GET_ADMIN(nextPtr));
  2735.         admin = MARK_FREE(thisBlockSize);
  2736.         SET_ADMIN(result, admin);
  2737.         nextPtr = result+thisBlockSize;
  2738.         }
  2739.         if (thisBlockSize >= bytesNeeded) {
  2740.         break;
  2741.         }
  2742.         if (thisBlockSize > memLargestFree) {
  2743.         memLargestFree = thisBlockSize;
  2744.         }
  2745.     }
  2746.  
  2747.     CHECK();
  2748.     /*
  2749.      * This block won't do the job.  Go on to the next block.
  2750.      */
  2751.  
  2752.     if (nextPtr != memLast) {
  2753.         result = nextPtr;
  2754.         continue;
  2755.     }
  2756.     CHECK();
  2757.  
  2758.     /*
  2759.      * End of the list.  If there's any chance that there's
  2760.      * enough free storage in the list to satisfy the request,
  2761.      * then go back to the beginning of the list and start
  2762.      * again.
  2763.      */
  2764.  
  2765.     if ((memLargestFree + memBytesFreed) > bytesNeeded) {
  2766.     CHECK();
  2767.         memLargestFree = 0;
  2768.         memBytesFreed = 0;
  2769.         result = memFirst;
  2770.         continue;
  2771.     }
  2772.     CHECK();
  2773.  
  2774.     /*
  2775.      * Not enough free space in the list.  Allocate a new region
  2776.      * of memory and add it to the list.
  2777.      */
  2778.  
  2779.     if (bytesNeeded < MIN_REGION_SIZE) {
  2780.         regionSize = MIN_REGION_SIZE;
  2781.     } else {
  2782.         regionSize = bytesNeeded + sizeof(AdminInfo);
  2783.     }
  2784.     CHECK();
  2785.     newRegion = MemChunkAlloc(regionSize);
  2786.     mem_NumLargeBytes += regionSize;
  2787.     CHECK();
  2788.  
  2789.     /*
  2790.      * If the new region immediately follows the end of the previous
  2791.      * region, merge them together.  At this point result always
  2792.      * points to a block of memory adjacent to and preceding the block
  2793.      * of memory pointed to by memLast (memLast == nextPtr).  Thus it
  2794.      * may be possible to merge the new region with both the region
  2795.      * at result and the one at nextPtr.
  2796.      */
  2797.  
  2798.     if (newRegion == (nextPtr+sizeof(AdminInfo))) {
  2799.         newRegion = nextPtr;
  2800.         regionSize += sizeof(AdminInfo);
  2801.         if (!IS_IN_USE(admin)) {
  2802.         newRegion = result;
  2803.         regionSize += SIZE(admin);
  2804.         }
  2805.     } else {
  2806.         SET_ADMIN(nextPtr, MARK_DUMMY(newRegion - nextPtr));
  2807.     }
  2808.     CHECK();
  2809.  
  2810.     /*
  2811.      * Create a dummy block at the end of the new region, which links
  2812.      * to "last".
  2813.      */
  2814.  
  2815.     SET_ADMIN(newRegion, MARK_FREE(regionSize - sizeof(AdminInfo)));
  2816.     memLast = newRegion + regionSize - sizeof(AdminInfo);
  2817.     SET_ADMIN(memLast, MARK_DUMMY(0));
  2818.     CHECK();
  2819.  
  2820.     /*
  2821.      * Continue scanning the list (try result again in case it
  2822.      * merged with the new region).
  2823.      */
  2824.     }
  2825.  
  2826.     /*
  2827.      * At this point we've got a block that's large enough.  If it's
  2828.      * larger than needed for the object, put the rest back on the
  2829.      * free list (note: even if the remnant is smaller than the smallest
  2830.      * large object, which means it'll be used by itself, we put it back
  2831.      * on the list so it can merge with either this block or the next,
  2832.      * whichever gets freed first).
  2833.      */
  2834.  
  2835.     CHECK();
  2836.     if (thisBlockSize < (bytesNeeded + sizeof(AdminInfo))) {
  2837.     SET_ADMIN(result, MARK_IN_USE(admin));
  2838.     CHECK();
  2839.     } else {
  2840.     SET_ADMIN(result+bytesNeeded, MARK_FREE(thisBlockSize-bytesNeeded));
  2841.     CHECK();
  2842.  
  2843.     (*(int *)(AdminInfo *) (result)) = (int) (bytesNeeded | 1);
  2844. #if 0    
  2845.     if (!(dxs == 0 || memcmp(dxs, dxp, sizeof(*dxp)) == 0)) {
  2846.  
  2847.         printf("FAILED, & = 0x%08x, dxs = 0x%08x, dxp=0x%08x\n",
  2848.         result, dxs, dxp);
  2849.  
  2850.         exit(1);
  2851.     }
  2852. #endif
  2853.  
  2854.     }
  2855.  
  2856. #ifdef MEM_TRACE
  2857.     SET_PC(result);
  2858.     CHECK();
  2859.     SET_ORIG_SIZE(result, origSize);
  2860.     CHECK();
  2861.     MemDoTrace(TRUE, result, (Address) NULL, bytesNeeded);
  2862.     CHECK();
  2863. #endif MEM_TRACE
  2864.     memCurrentPtr = result;
  2865.     CHECK();
  2866.  
  2867.     UNLOCK_MONITOR;
  2868.     CHECK();
  2869.     return(result+sizeof(AdminInfo));
  2870. }
  2871.  
  2872.  
  2873.